深度学习-基于Pytorch 的cifar-10_AlexNet 实践
ztj100 2024-10-31 16:14 13 浏览 0 评论
我是一个初学者,将学习《动手学习深度学习》课程的内容记录如下:
主要内容参考原文,也加了一些查阅资料。
cifar-10 是一个典型的图像分类问题,
首先进入数据训练模型阶段,我学习的时候将相关学习都写着注释里面,方便看,具体代码如下:
# -*- coding: utf-8 -*-
# @Time : 2021/12/7 9:43
# @Author :
# @Email :
# @File : cifar-10_alexNet.py
import numpy as np
import torch
import torchvision
import torchvision.transforms as transforms
# torchvision,实现了常用的一些深度学习的相关的图像数据的加载功能,
# 比如cifar10、Imagenet、Mnist等等的,保存在torchvision.datasets模块中
import torch.utils.data as Data
from torch import nn
from torch.nn import functional as F
import torch.optim as optim
from torch.autograd import Variable
from torchsummary import summary
import os
import time
import matplotlib.pyplot as plt
# 定义函数用于查看部分数据
def imshow(img,title = None):
#normalized x = (x - mean) / std
img = img * 0.225 + 0.45 #unnormalized dataloader 时做了 normalized
npimg = img.numpy() # 将 torch.FloatTensor 转换为 numpy的格式 *255
#npimg = npimg.astype(np.uint8)
# plt.imshow(np.transpose(npimg, (1, 2,0)))。
# 因为在plt.imshow在现实的时候输入的是(imagesize,imagesize,channels),
# 而def imshow(img,text,should_save=False)中,参数img的格式为(channels,imagesize,imagesize),
# 这两者的格式不一致,我们需要调用一次np.transpose函数,
plt.imshow(np.transpose(img,(1,2,0)))
plt.axis('off')
#plt.imshow(img) #此处有可能有警告,或者报错,原因就是归一化的时候和显示还原不一致。
if title is not None:
plt.title(title)
# 构建网络,继承nn.Module
class CNNNet(nn.Module):
def __init__(self):
super(CNNNet, self).__init__()
# 添加第一个卷积层
# Conv2d(1,20,5)表示,输入是1通道的图像,输出是20通道,也就是20个卷积核,卷积核尺寸是5*5,其余参数默认值
self.conv1 = nn.Conv2d(in_channels=3,out_channels=16,kernel_size=5,stride=1)
# MaxPool2d(2,2)
self.pool1 = nn.MaxPool2d(kernel_size=2,stride=2)
self.conv2 = nn.Conv2d(in_channels=16,out_channels=36,kernel_size=3,stride=1)
self.pool2 = nn.MaxPool2d(kernel_size=2,stride=2)
# 接着定义全连接层
self.fc1 = nn.Linear(1296,128)
self.fc2 = nn.Linear(128,10)
# 定义前向传播函数
def forward(self,x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
# print(x.shape) 应该是:torch.Size([4, 36, 6, 6])
# .view() 改变tensor size,但是元素总数不变
# -1 表示:这个参数由另一个元素确定,比如矩阵元素总数确定的情况下,列数确定了之后,行数也可以确定
# 全连接层 就是矩阵的乘法,保证2个矩阵可以相乘,所以把X 调整到正确的size
x = x.view(-1,36*6*6)
x = F.relu(self.fc2(F.relu(self.fc1(x))))
return x
# 定义AlexNet
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.Conv = nn.Sequential(
# IN : 3*32*32
nn.Conv2d(in_channels=3, out_channels=96, kernel_size=5, stride=2, padding=2),
# 论文中kernel_size = 11,stride = 4,padding = 2
nn.ReLU(),
# IN : 96*16*16
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# IN : 96*8*8
nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
# IN :256*8*8
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# IN : 256*4*4
nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# OUT : 384*2*2
)
self.linear = nn.Sequential(
nn.Linear(in_features=384 * 2 * 2, out_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=10),
)
def forward(self, x):
x = self.Conv(x)
x = x.view(-1, 384 * 2 * 2)
x = self.linear(x)
return x
# 显示网络参数量
def Init_net():
model = AlexNet()
model.to(device)
data_input = Variable(torch.randn(8,3,32,32))
print(data_input.size())
data_input.to(device)
model(data_input)
print(summary(model,(3,32,32)))
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
# 有GPU,优先用GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# **由于torchvision的datasets的输出是[0,1]的PILImage,所以我们先先归一化为[-1,1]的Tensor**
# 首先定义了一个变换transform,利用的是上面提到的transforms模块中的Compose( )
# 把多个变换组合在一起,可以看到这里面组合了ToTensor和Normalize这两个变换
transform = transforms.Compose(
[transforms.ToTensor(), #range [0, 255] -> [0.0,1.0]
transforms.Normalize((0.45, 0.45, 0.45), (0.225, 0.225, 0.225))] # Normalize()函数去计算 x = (x - mean)/std
)
# 前面的(0.5,0.5,0.5)是RGB三个通道上的均值,后面(0.5, 0.5, 0.5)是三个通道的标准差,
# 注意通道顺序是RGB ,用过opencv的同学应该知道openCV读出来的图像是BRG顺序。
# 这两个tuple数据是用来对RGB图像做归一化的.这里均值和标准差都是近似的值,可以在数据集中计算。
# 利用torchvision数据收集,train=True表示拉取训练集,FALSE表示测试集,num_workers:用多少个子进程加载数据。0表示数据将在主进程中加载(默认: 0)
# DataLoader:pin_memory=True,意味着生成的Tensor属于内存的锁业内存,这样转GPU的时候快一些
trainset = torchvision.datasets.CIFAR10('./data', train=True, download=True, transform=transform)
trainloader = Data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2,pin_memory=True)
testset = torchvision.datasets.CIFAR10('./data', train=False, download=True, transform=transform)
testloader = Data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2,pin_memory=True)
print("训练数据数量:", len(trainset))
print("训练数据分为4份后数量:", len(trainloader))
print("测试数据数量:", len(testset))
print("测试数据分为4份后数量:", len(testloader))
classes = ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
# 随机获取部分训练数据,创建一个迭代器,可以调用 next 下一个对象
dataiter = iter(trainloader)
imges,labels = dataiter.next() # 包大小为4,所以一份有 4 个值,len(x) = 4
#print(len(imges[0]))
print(device)
# 显示个batch 图像
for num in range(imges.shape[0]):
plt.subplot(1,4,num+1)
imshow(imges[num],classes[labels[num].item()])
plt.show() #此处有可能有警告,或者报错,原因就是归一化的时候和显示还原不一致。
# imshow(torchvision.utils.make_grid(imges)) #直接以格子的形式展现
# print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
# 打印初始化网络,查看网络情况
# Init_net()
# net = CNNNet()
net = AlexNet()
net = net.to(device=device)
# 可以打印网络查看一下
print(net)
# 定义优化器和损失函数
criterion = nn.CrossEntropyLoss() #nn工具箱中的交叉熵损失函数
# 使用nn工具箱中的 SGD 梯度优化算法(随机梯度下降)
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)
# 优化器:pytorch将深度学习中常用的优化方法全部封装在torch.optim之中,所有的优化方法都是继承基类optim.Optimizier
# 如果要使用GPU,在定义优化器之前,就要完成 .cuda()操作
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# 下面进入训练操作
start_time = time.time()
for epoch in range(6): # loop over the dataset multiple times 指定训练一共要循环几个epoch
running_loss = 0.0 #定义一个临时变量,用于记录和输出loss
for i,data in enumerate(trainloader,0):
#传入训练数据,enumerate
# data 是从enumerate 返回的,包含数据和标签信息,分别赋值inputs和labels
inputs,labels = data
# copy数据到设备,如果使用CPU,这一步是多余的
inputs,labels = inputs.to(device),labels.to(device)
# 将数据转换成Variable,
# 注意:虽然官网给的程序有这么一句 from torch.autograd import Variable,
# 但是此步中确实没有显式地用到variable,也可以不用转,下一步
# 只能说网络里运行的数据确实要以variable的形式存在
#inputs, labels = Variable(inputs), Variable(labels)
optimizer.zero_grad()#要把梯度重新归零,因为反向传播过程中梯度会累加上一次循环的梯度
# forward + backward + optimize
outputs = net(inputs) #把数据输入网络中
loss = criterion(outputs,labels) #计算损失值
# 想要计算各个variable的梯度,只需调用根节点的backward方法,Autograd就会自动沿着整个计算图进行反向计算
# 而在此例子中,根节点就是我们的loss,所以:
# 程序中的loss.backward()代码就是在实现反向传播,自动计算所有的梯度。
loss.backward() #反向传递损失函数
optimizer.step() #反向传播之后,把优化器的参数进行更新,方便下一轮运算
# 下面打印loss结果,方便查看损失值,但与训练关系不大
running_loss += loss.item() #此处选择每2000 累计一次损失值
# 从下面一行代码可以看出它是每循环0-1999共两千次才打印一次
if i % 2000 == 1999:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
'[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0 # 重新初始化,下次再使用
endtime = time.time()
print("训练完成,训练用时:%f S"%(endtime - start_time))
# 测试训练情况
# 查看测试集数据
dataiter = iter(testloader) #创建迭代器
images,labels = dataiter.next() #返回一个batch_size的图片
# imshow(torchvision.utils.make_grid(images)) # 展示这四张图片
# 显示个batch 图像
for num in range(imges.shape[0]):
plt.subplot(1, 4, num + 1)
imshow(imges[num], classes[labels[num].item()])
# plt.show()
# print('GroundTruth: ', ' '.join(
# '%5s' % classes[labels[j]] for j in range(4))) # python字符串格式化 ' '.join表示用空格来连接后面的字符串,参考python的join()方法
start_time = time.time()
# images, labels = images.to(device), labels.to(device)
# outputs = net(Variable(images)) # 注意这里的images是我们从上面获得的那四张图片,所以首先要转化成variable
# 返回返回输入Tensor中每行的最大值,并转换成指定的dim(维度);
# 参数dim=1,相当于调用了squeeze(1),如果dim=0,它其实是在返回每列的最大值
# 这里很明显,这个返回的元组的第一个元素是image data,即是最大的值,第二个元素是label, 即是最大的值的索引
# 我们只需要label(最大值的索引),所以就会有 _ , predicted这样的赋值语句
# _, predicted = torch.max(outputs.data, 1)
# 这个 _ , predicted是python的一种常用的写法,表示后面的函数其实会返回两个值
# 但是我们对第一个值不感兴趣,就写个_在那里,把它赋值给_就好,我们只关心第二个值predicted
# 比如 _ ,a = 1,2 这中赋值语句在python中是可以通过的,你只关心后面的等式中的第二个位置的值是多少
# print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4))) # python的字符串格式化
correct = 0 # 定义预测正确的图片数,初始化为0
total = 0 # 总共参与测试的图片数,也初始化为0
# 在使用pytorch时,并不是所有的操作都需要进行计算图的生成(计算过程的构建,以便梯度反向传播等操作)。
# 而对于tensor的计算操作,默认是要进行计算图的构建的.
# 在这种情况下,可以使用 with torch.no_grad():强制之后的内容不进行计算图构建。
with torch.no_grad():
for data in testloader: # 循环每一个batch
images, labels = data
# copy数据到设备,如果使用CPU,这一步是多余的
images, labels = images.to(device), labels.to(device)
outputs = net(images) # 输入网络进行测试
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0) # 更新测试图片的数量
correct += (predicted == labels).sum().item() # 更新正确分类的图片的数量
print('Accuracy of the network on the 10000 test images: %d %%' % (
100 * correct / total)) # 最后打印结果
endtime = time.time()
print("测试完成,测试用时:%f S"%(endtime - start_time))
# 打印各个类别的识别准确率,这看起来比随机预测要好,
# 随机预测的准确率为10%(随机预测出为10类中的哪一类)。
# 看来网络学到了东西。
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
t = 0
with torch.no_grad():
for data in testloader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = net(images)
_, predicted = torch.max(outputs, 1)
c = (predicted == labels).squeeze()
for i in range(4):
label = labels[i]
class_correct[label] += c[i].item()
class_total[label] += 1
for i in range(10):
print('Accuracy of %5s : %2d %%' % (
classes[i], 100 * class_correct[i] / class_total[i]))
# 只保存网络中训练好的权重文件,使用的时候会快一些
print('===> Saving models...')
path_model = './model'
state = {
'state': net.state_dict(),
'epoch': epoch # 将epoch一并保存
}
if not os.path.isdir('model'): # 如果没有这个目录就创建一个
os.mkdir('./model')
# 保存整个网络模型,也可以保存整个模型
torch.save(net,"./model/cifar-10_alxNet_model.pkl")
# 保存模型的参数,参数后续使用快于整个模型
torch.save(net.state_dict(), './model/cifar-10_alxNet_model_params.pkl')
接下来是训练好模型后具体的使用环节,下面还是继续用Python来体验:
# -*- coding: utf-8 -*-
# @Time : 2021/12/7 9:43
# @Author :
# @Email :
# @File : use_AlexNet.py
import os
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
import time
import json
import torch
from torch import nn
import torchvision.transforms as transforms
from PIL import Image,ImageFont,ImageDraw
import torch.optim as optim
from matplotlib import pyplot as plt
import torchvision.models as models
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
classes = ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
#图像预处理,必须转换成和模型相同的尺寸,否则将无法识别
image_transforms = {
'test': transforms.Compose([
transforms.Resize(size=32),
transforms.CenterCrop(size=32),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
}
# 定义AlexNet
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.Conv = nn.Sequential(
# IN : 3*32*32
nn.Conv2d(in_channels=3, out_channels=96, kernel_size=5, stride=2, padding=2),
# 论文中kernel_size = 11,stride = 4,padding = 2
nn.ReLU(),
# IN : 96*16*16
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# IN : 96*8*8
nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
# IN :256*8*8
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# IN : 256*4*4
nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# OUT : 384*2*2
)
self.linear = nn.Sequential(
nn.Linear(in_features=384 * 2 * 2, out_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=10),
)
def forward(self, x):
x = self.Conv(x)
x = x.view(-1, 384 * 2 * 2)
x = self.linear(x)
return x
def predict(model, test_image_name):
transform = image_transforms['test']
test_image = Image.open(test_image_name).convert('RGB')
draw = ImageDraw.Draw(test_image)
test_image_tensor = transform(test_image)
if torch.cuda.is_available():
test_image_tensor = test_image_tensor.view(1, 3, 32, 32).cuda()
else:
test_image_tensor = test_image_tensor.view(1, 3, 32, 32)
with torch.no_grad():
model.eval()
out = model(test_image_tensor)
# print("out=",out)
ps = torch.exp(out)
topk, topclass = ps.topk(1, dim=1)
print("Prediction : ", classes[topclass.cpu().numpy()[0][0]], ", Score(exp): ", topk.cpu().numpy()[0][0])
text = classes[topclass.cpu().numpy()[0][0]] + "\nScore(exp):" + str(topk.cpu().numpy()[0][0])
font = ImageFont.truetype('arial.ttf', 36)
draw.text((0, 0), text, (255, 0, 0), font=font)
test_image.show()
if __name__ == "__main__":
# config
path_state_dict = os.path.join(BASE_DIR, "cifar-10_alxNet_model.pkl") #字符串组合,上文中保存的模型路径
path_img = os.path.join(BASE_DIR, "..", "data", "111.png") #填写图片地址和名称
# load model
# 由于训练模型是在GPU上训练的,如果在没有GPU的设备上运行时,需要加map_location
model = torch.load(path_state_dict, map_location=torch.device(device))
predict(model,path_img) #预测图像中的物体,为提高识别率,可采用集成的方式
识别效果:
可寻找对应图片数据传入模型预测:
相关推荐
- 从IDEA开始,迈进GO语言之门(idea got)
-
前言笔者在学习GO语言编程的时候,GO语言在国内还没有像JAVA/Php/Python那样普及,绕了不少的弯路,要开始入门学习一门编程语言,最好就先从选择一个好的编程语言的开发环境开始,有了这个开发环...
- 基于SpringBoot+MyBatis的私人影院java网上购票jsp源代码Mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于SpringBoot...
- 基于springboot的个人服装管理系统java网上商城jsp源代码mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...
- 基于springboot的美食网站Java食品销售jsp源代码Mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...
- 贸易管理进销存springboot云管货管账分析java jsp源代码mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目描述贸易管理进销存spring...
- SpringBoot+VUE员工信息管理系统Java人员管理jsp源代码Mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍SpringBoot+V...
- 目前见过最牛的一个SpringBoot商城项目(附源码)还有人没用过吗
-
帮粉丝找了一个基于SpringBoot的天猫商城项目,快速部署运行,所用技术:MySQL,Druid,Log4j2,Maven,Echarts,Bootstrap...免费给大家分享出来前台演示...
- SpringBoot+Mysql实现的手机商城附带源码演示导入视频
-
今天为大家带来的是基于SpringBoot+JPA+Thymeleaf框架的手机商城管理系统,商城系统分为前台和后台、前台用的是Bootstrap框架后台用的是SpringBoot+JPA都是现在主...
- 全网首发!马士兵内部共享—1658页《Java面试突击核心讲》
-
又是一年一度的“金九银十”秋招大热门,为助力广大程序员朋友“面试造火箭”,小编今天给大家分享的便是这份马士兵内部的面试神技——1658页《Java面试突击核心讲》!...
- SpringBoot数据库操作的应用(springboot与数据库交互)
-
1.JDBC+HikariDataSource...
- SpringBoot 整合 Flink 实时同步 MySQL
-
1、需求在Flink发布SpringBoot打包的jar包能够实时同步MySQL表,做到原表进行新增、修改、删除的时候目标表都能对应同步。...
- SpringBoot + Mybatis + Shiro + mysql + redis智能平台源码分享
-
后端技术栈基于SpringBoot+Mybatis+Shiro+mysql+redis构建的智慧云智能教育平台基于数据驱动视图的理念封装element-ui,即使没有vue的使...
- Springboot+Mysql舞蹈课程在线预约系统源码附带视频运行教程
-
今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的Springboot+Mysql舞蹈课程在线预约系统,系统项目源代码在【猿来入此】获取!https://www.yuan...
- SpringBoot+Mysql在线众筹系统源码+讲解视频+开发文档(参考论文
-
今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的在线众筹管理系统,主要实现了普通用户在线参与众筹基本操作流程的全部功能,系统分普通用户、超级管理员等角色,除基础脚手架外...
- Docker一键部署 SpringBoot 应用的方法,贼快贼好用
-
这两天发现个Gradle插件,支持一键打包、推送Docker镜像。今天我们来讲讲这个插件,希望对大家有所帮助!GradleDockerPlugin简介...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 从IDEA开始,迈进GO语言之门(idea got)
- 基于SpringBoot+MyBatis的私人影院java网上购票jsp源代码Mysql
- 基于springboot的个人服装管理系统java网上商城jsp源代码mysql
- 基于springboot的美食网站Java食品销售jsp源代码Mysql
- 贸易管理进销存springboot云管货管账分析java jsp源代码mysql
- SpringBoot+VUE员工信息管理系统Java人员管理jsp源代码Mysql
- 目前见过最牛的一个SpringBoot商城项目(附源码)还有人没用过吗
- SpringBoot+Mysql实现的手机商城附带源码演示导入视频
- 全网首发!马士兵内部共享—1658页《Java面试突击核心讲》
- SpringBoot数据库操作的应用(springboot与数据库交互)
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)