写在前面:
本人小白研一, 刚开始学习深度学习, 将自己的第一个实验过程总结下来, 看了很多的大牛的博客, 在下面的程序中也参考了很多大牛的博客. 在刚开始入门的学习的时候, 直接编写程序下载数据集, 但是后来觉得可能会用到自己手动构建数据集. 所以自己参考了一些博客, 尝试了从自己手动构造数据集 -- 搭建 Resnet34 网络 -- 训练 -- 验证的一整个过程. 下面将自己的实验过程记录如下. 本文重点介绍自己构建数据集与神经网络搭建部分
本人才疏学浅, 刚入门, 有错误纰漏的地方恳请各位批评指正.
第一章:
首先需要自己构建 Mnist 数据集, 当然也可以自己从网络上下载. 在这里, 由于本人有点作, 想尝试自己构造数据集, 话不多说, 直接贴代码
- #!/usr/bin/env python 3.6
- #_*_coding:utf-8 _*_
- #@Time :2019/11/7 9:10
- #@Author : 控制工程小白
- #@FileName: 自己制作 Mnist 数据集. py
- #@Software: PyCharm
- import torch
- import torchvision
- from skimage import io
- #import os
- mnist_train=torchvision.datasets.MNIST('./make_mnistdata',train=True,download=True)# 首先下载数据集, 并数据分割成训练集与数据集
- mnist_test=torchvision.datasets.MNIST('./make_mnistdata',train=False,download=True)
- print('testset:',len(mnist_test))
- #txt_path = "G:/Mnist_Recognition/mnist_label.txt"
- # if not os.path.exists(txt_path):
- # os.makedirs(txt_path)
- f=open("./mnist_test.txt",'w')# 在指定路径之下生成. txt 文件
- for i,(img,label) in enumerate(mnist_test):
- img_path = "./mnist_test/" + str(i) + ".jpg"
- io.imsave(img_path, img)# 将图片数据以图片. jpg 格式存在指定路径下
- img_paths=img_path+str(i)+".jpg"
- f.write(img_path+''+str(label)+'\n')# 将路径与标签组合成的字符串存在. txt 文件下
- f.close()# 关闭文件
注意, 在运行这段代码之前应该在根目录下新建一个 mnist_train 文件夹用于存放训练集的图片, 新建 mnist_test 文件夹用于存放测试集的图片, 运行这段代码之后会生成一个 mnist_test.txt 与 mnist_train.txt 文件, 用来储存各个字符串, 这个字符串由每个图片的路径与对应的标签组成, 至于这样做有什么用, 请看下文. 贴一下上述代码运行结果
第二章:
下面将会用到上一章生成的. txt 文件, 先上代码
- #!/usr/bin/env python 3.6
- #_*_coding:utf-8 _*_
- #@Time :2019/11/7 11:38
- #@Author : 控制工程小白
- #@FileName: My_dataset.py
- #@Software: PyCharm
- from PIL import Image
- import torch
- from torch.utils import data
- import torchvision.transforms as transforms
- from torch.utils.data import DataLoader
- import matplotlib.pyplot as plt
- class MyDataset(data.Dataset):
- def __init__(self,datatxt,transform=None,target_transform=None):
- super(MyDataset,self).__init__()
- fh=open(datatxt,'r')# 读取标签文件. txt
- imgs=[]# 暂时定义一个空的列表
- for line in fh:
- line.strip('\n')# 出去字符串末尾的空格, 制表符
- words=line.split()# 将路径名与标签分离出来
- imgs.append((words[0],int(words[1])))#Word[0] 表示图片的路径名, Word[1] 表示该数字图片对应的标签
- self.imgs=imgs
- self.transform=transform
- self.target_transform=target_transform
- #self.loader=loader
- def __getitem__(self, index):
- fn,label=self.imgs[index]#fn 表示图片的路径
- img = Image.open(fn)#.convert('RGB'), 这里时候需要转换成 RGB 图像视神经网络结构而定, 读取文件的路径名, 也即打开图片
- if self.transform is not None:
- img=self.transform(img)
- return img,label# 返回图片与标签
- def __len__(self):
- return len(self.imgs)
这段代码构造了一个类, 用于获取刚刚建立的数据集, 思想就是读取刚刚建立的. txt 文件, 将其中的图片的路径名与该图片对应的标签分离, 然后根据根据图片的路径名获取数据集.
第三章:
搭建神经网络, 随着深度学习的发展, 已经出现了很多种神经网络, 一般而言, 神经网络越深越好, 但是神经网络的维度太深的话, 会导致神经网络过拟合, 于是开发者开发了一种残差神经网络 Resnet, 它是由很多个残差快组成, 每个残差块都包含跳连接, 防止过拟合, 这样可以达到网络更深同时性能不会受到过拟合的影响.
下面直接贴 Resnet34 代码
- #!/usr/bin/env python 3.6
- #_*_coding:utf-8 _*_
- #@Time :2019/11/7 15:44
- #@Author :hujinzhou
- #@FileName: neural_network4.py
- #@Software: PyCharm
- import torch.nn as nn
- class Reslock(nn.Module):
- def __init__(self, in_channels, out_channels, stride=1):
- super(Reslock, self).__init__()
- self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
- self.bn1 = nn.BatchNorm2d(out_channels)
- self.relu = nn.ReLU(inplace=True)
- self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
- self.bn2 = nn.BatchNorm2d(out_channels)
- if in_channels != out_channels:
- self.downsample = nn.Sequential(
- nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=2),
- nn.BatchNorm2d(out_channels)
- )
- else:
- self.downsample = None
- def forward(self, x):
- identity = x
- out = self.conv1(x)
- out = self.bn1(out)
- out = self.relu(out)
- out = self.conv2(out)
- out = self.bn2(out)
- if self.downsample is not None:
- identity = self.downsample(x)
- out += identity
- out = self.relu(out)
- return out
- class ResNet34(nn.Module):
- def __init__(self, num_classes=10):
- super(ResNet34, self).__init__()
- self.first = nn.Sequential(
- nn.Conv2d(1, 64, 7, 2, 3),
- nn.BatchNorm2d(64),
- nn.ReLU(inplace=True),
- nn.MaxPool2d(3, 1, 1)
- )
- self.layer1 = self.make_layer(64, 64, 3, 1)
- self.layer2 = self.make_layer(64, 128, 4, 2)
- self.layer3 = self.make_layer(128, 256, 6, 2)
- self.layer4 = self.make_layer(256, 512, 3, 2)
- self.avg_pool = nn.AvgPool2d(2)
- self.fc = nn.Linear(512, num_classes)
- def make_layer(self, in_channels, out_channels, block_num, stride):
- layers = []
- layers.append(Reslock(in_channels, out_channels, stride))
- for i in range(block_num - 1):
- layers.append(Reslock(out_channels, out_channels, 1))
- return nn.Sequential(*layers)
- def forward(self, x):
- x = self.first(x)
- x = self.layer1(x)
- x = self.layer2(x)
- x = self.layer3(x)
- x = self.layer4(x)
- x = self.avg_pool(x)
- # x.size()[0]: batch size
- x = x.view(x.size()[0], -1)
- x = self.fc(x)
- return x
第四章:
上述过程弄好了, 下面的过程就非常简单了, 下面直接训练并识别验证就可以了, 训练代码与验证代码就很简单了, 在本文中直接贴训练结果图与识别精度图
来源: https://www.cnblogs.com/hujinzhou/p/jiazhou2019_6_1.html