pytorch手写图片识别,其中还有一些小细节哦
这是一篇pytorch实现手写图片识别文章,这其中还有自己的一定见解。
有错误的地方,还麻烦指正。
以下内容全为4D张量下的个人结论:
这里在pytorch中有个细节,如果是你自己的数据,在进行训练时候,你需要把图片转成tensor,那么在转换的时候,要保证机器的运行效率,以及虚拟内存的使用,太大就会超标,直接算不了了。
所以,一般把图片归一化,emmm,就是把他的numpy数据除以255。
img = img/255.0
为了减少占有空间把图片类型转为float32
img = img.astype('float32')
当然也可以改成float16
还有一个重要的地方是,当我们对训练集进行reshape时,可以根据上面4D张量来写,也就是说
train_data = train_data.reshape(10000,28,28,1)
但是我也遇见了必须把1写在样本量后边,卷积层in_channels才会等于1,不然就会等于28。
例如:
train_data = train_data.reshape(10000,1,28,28)
这个地方我查了很多资料,也问了老师,翻到了keras文档的时候刚好看见了关于这个东西的解答。
解答链接.
reshape之后把数据转成tensor就可以啦
文档解答内容:
data_format:字符串,“channels_first”或“channels_last”之一,代表图像的通道维的位置。该参数是Keras 1.x中的image_dim_ordering,“channels_last”对应原本的“tf”,“channels_first”对应原本的“th”。以128x128的RGB图像为例,“channels_first”应将数据组织为(3,128,128),而“channels_last”应将数据组织为(128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channels_last”。
害,这大概就是学习把。
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt
import numpy as np
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
EPOCH = 1
BATCH_SIZE = 50
LR = 0.001
DOWNLOAD_MNIST = False
train_data = torchvision.datasets.MNIST(
root='./mnist',
train=True,
transform=torchvision.transforms.ToTensor(),
download=DOWNLOAD_MNIST
)
# plt.imshow(train_data.data[0].numpy(),cmap='gray')
# plt.show()
train_loader = Data.DataLoader(train_data,batch_size=BATCH_SIZE,shuffle=True,num_workers=2)
test_data = torchvision.datasets.MNIST(root='./mnist',train=False)
test_x = Variable(torch.unsqueeze(test_data.data,dim=1),volatile=True).type(torch.float32)[:2000]/255
test_y = test_data.targets[:2000]
class CNN(nn.Module):
def __init__(self):
super(CNN,self).__init__()
self.conv1 = nn.Sequential(
nn.Conv2d( #(1,28,28)
in_channels=1, #1代表着灰度图片,,如果是3这个地方就是代表彩色图片
out_channels=16, #输出的特征值16个
kernel_size=5, #5x5卷积核
stride=1, # 步长,每次移动一个像素
padding=2, #扩充边缘,方便提取边缘特征 padding = (kernel_size-1)/2
), #图片变成(16,28,28)
nn.ReLU(),
nn.MaxPool2d(kernel_size=2), #这个地方使用2x2的区域再一次卷积/ 变成(32,14,14)
)
self.conv2 = nn.Sequential(
nn.Conv2d(16,32,5,1,2), #变成(32,14,14)
nn.ReLU(),
nn.MaxPool2d(2), #变成(32,7,7)
)
self.out = nn.Linear(32*7*7,10)
def forward(self,x): #进行展平
x = self.conv1(x)
x = self.conv2(x)
x = x.view(x.size(0),-1) #(batch,32*7*7)
output = self.out(x)
return output
if __name__=='__main__':
cnn = CNN()
optimizer = torch.optim.Adam(cnn.parameters(),lr=LR) #优化器
loss_fun = nn.CrossEntropyLoss() #自带softmax
for epoch in range(EPOCH):
for step, (b_x, b_y) in enumerate(train_loader):
output = cnn(b_x)
loss = loss_fun(output, b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if step % 50 == 0:
test_output = cnn(test_x)
pred_y = torch.max(test_output, 1)[1].data.numpy()
accuracy = (sum(pred_y == np.array(test_y.data)).item()) / test_y.size(0)
print('Epoch:', epoch, '| train loss:%.4f' % loss.item(), '| test accuracy:%.4f' % accuracy)
代码的预测部分就没有写了,文中提及的内容,可能跟本代码无关,是我在写另外的cnn图像分类发现的问题,当然也当作学习,有空会把另外一篇关于岩石分类整理出来的。
兄弟们时间到了,再见。