深度学习入门指南:从零开始TinyMind汉字书法识别

这几天在刷这个新出的比赛,受举办方邀请谢了一篇文章,也转到CSDN来和大家分享下吧。话说TinyMind不是被CSDN收购了么,我这算不算把统一个发了两遍23333

  • 环境搭建
  • 数据导入
  • 启动网络

环境搭建:

对入门来说,最容易的还是在windows下进行开发。而且现在各种深度学习架构大都支持windows,因此如果只是入门深度学习,最好还是从windows开始。不过因为github上提交的代码全都运行在linux环境下,因此希望大家最终能转向linux下,话不多说,现在开始。

我们选用的深度学习架构是pytorch, 相比于tensorflow,pytorch更加简单易用,而且符合python的编程习惯,官网的支持也足够完善。

环境搭建步骤

  1. 安装Anaconda, 装python3.6版本的,至于为啥用python3这都2018年了,就别用上古版本了
  2. 安装pycharm,将pycharm的解释器改为anaconda安装目录下的python。当然用别的IDE也可以,但是我习惯用pycahrm了,如果大家用别的IDE这步另当别论
  3. 安装深度学习架构pytorch, 到了最重要的步骤了,如果没有英伟达显卡,或者显卡不支持请忽略1-3步
    1. 安装英伟达显卡驱动
    2. 安装CUDA
    3. 安装Cuddn
    4. 安装pytorch gpu版 (没有显卡的装cpu版)具体方法参见知乎这篇文章 https://zhuanlan.zhihu.com/p/26871672 选择自己对应的版本、系统、cuda版本,按照命令直接装就可以

数据导入

数据下载在TinyMind的比赛网站 http://www.tinymind.cn/competitions/41
下载解压后是两部分,分别是train和test1,其中train是训练集,test1是用来提交评分的测试集
为了导入图片数据,需要调用opencv,没装opencv的话就先装opencv

conda install -c https://conda.binstar.org/menpo opencv
import os
import numpy as np
import torch
import torch.utils.data as data
import cv2
from PIL import Image
from tqdm import tqdmtrainpath = 'E:\\Code\\TMD1st\\train\\' #这是我的储存路径,windows下的路径是需要用\\隔开的,linux是反斜杠/
testpath = 'E:\\Code\\TMD1st\\test1\\'
words = os.listdir(trainpath)   # 按时间排序 从早到晚
category_number = len(words) # 一共有多少个字img_size = (256, 256) #将图片大小统一设定为这个值def loadOneWord(order):path = trainpath + words[order] + '\\'files = os.listdir(path)datas = []for file in files:file = path + fileimg = np.asarray(Image.open(file))img = cv2.resize(img, img_size)datas.append(img)datas = np.array(datas)labels = np.zeros([len(datas), len(words)], dtype=np.uint8)labels[:, order] = 1return datas, labelsdef transData():    #将所有数据转存,以后就不用每次都从原始数据读取了num = len(words)datas = np.array([], dtype=np.uint8)datas.shape = -1, 256, 256labels = np.array([], dtype=np.uint8)labels.shape = -1, 100for k in range(num):data, label = loadOneWord(k)datas = np.append(datas, data, axis=0)labels = np.append(labels, label, axis=0)print('loading', k)np.save('data.npy', datas) #将数据和标签分别存为data和labelnp.save('label.npy', labels)

将转存完的结果读出来看一下

if __name__ == '__main__':datas = np.load('data.npy')labels = np.load('label.npy')index = np.arange(0, len(datas), 1, dtype=np.int)print(datas.shape, labels.shape)

(40000, 256, 256) (40000, 100)

我是将40000个图像的label按照one-hot编码存的,这么干其实浪费空间,但是反正也没几兆,就懒得改了,index那一行就是专为将ong-hot转label

这才将数据转存,为了训练时给pytorch使用,最方便的方法是使用pytorch做好的loader工具,为此需要实现自己的data.Dataset。只需继承data.Dataset,并且重写getitemlen两个方法就可以。

class TrainSet(data.Dataset):def __init__(self, eval=False):datas = np.load('data.npy') #装载labels = np.load('label.npy')index = np.arange(0, len(datas), 1, dtype=np.int) #换one-hot为labelnp.random.seed(123)np.random.shuffle(index)if eval:    #如果eval为真,就取10%作为验证集,设定随机数种子是为了每次取出来的都是固定的10%,以免将验证集用于训练index = index[:int(len(datas) * 0.1)]else:index = index[int(len(datas) * 0.1):]self.data = datas[index]self.label = labels[index]np.random.seed()def __getitem__(self, index):return torch.from_numpy(self.data[index]), \torch.from_numpy(self.label[index])def __len__(self):return len(self.data)

完成dataset后只要使用torch.utils.data.DataLoader就可以自动划分batch。

启动网络

无论网络结构如何,用网络进行训练的整个过程是相同的

import torch
import torch.optim as optim
from torch.autograd import Variable
import torch.nn as nn
import data
import torch.nn.functional as Fn_epoch, batch_size = 25, 8 # 设置遍历次数及每个batch的大小trainset = data.TrainSet(eval=False) #实例化上面定义的数据集对象
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True) #用trainset实例化loader
evalset = data.TrainSet(eval=True)  #验证集
evalloader = torch.utils.data.DataLoader(evalset, batch_size=batch_size, shuffle=True)net = Net() # 实例化模型
if torch.cuda.is_available():   # 将模型移到GPU上net.cuda()
criterion = nn.CrossEntropyLoss()   #损失函数使用交叉熵
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=1e-1, weight_decay=1e-4) #优化器使用SGD 学习率1e-3def train(epoch):net.train() # 经模型切换到训练模式correct = 0sum = 0for batch_index, (datas, labels) in enumerate(trainloader, 0):  #从loader装载数据labels = labels.max(1)[1]datas = Variable(datas).float()datas = datas.view(-1, 1, 256, 256)labels = Variable(labels).long()if torch.cuda.is_available():   #数据转移到GPUdatas = datas.cuda()labels = labels.cuda()optimizer.zero_grad()   # 每次前项计算之前,将优化器梯度清零outputs = net(datas)    # 前项计算loss = criterion(outputs, labels) # 根据结果和label计算损失函数loss.backward() # 做反向传播optimizer.step() # 用优化器进行一次更新pred_choice = outputs.data.max(1)[1]    # 前向输出计算最大的一个作为最可能的输出correct += pred_choice.eq(labels.data).cpu().sum() # 统计正确个数sum += len(labels)  # 总数# 输出每次计算的信息print('batch_index: [%d/%d]' % (batch_index, len(trainloader)),'Train epoch: [%d]' % (epoch),# 'acc:%.4f p:%.4f r:%.4f F1:%.4f' % (acc, p, r, F1),'correct/sum:%d/%d, %.4f' % (correct, sum, correct / sum))def eval(epoch):    # 用验证集做类似过程,只是不计算梯度、不更新参数net.eval()correct = 0sum = 0for batch_index, (datas, labels) in enumerate(evalloader, 0):labels = labels.max(1)[1]datas = Variable(datas).cuda().float()datas = datas.view(-1, 1, 256, 256)labels = Variable(labels).cuda().long()# optimizer.zero_grad()outputs = net(datas)# loss = criterion(outputs, labels)# loss.backward()# optimizer.step()pred_choice = outputs.data.max(1)[1]correct += pred_choice.eq(labels.data).cpu().sum()sum += len(labels)print('batch_index: [%d/%d]' % (batch_index, len(evalloader)),'Eval epoch: [%d]' % (epoch),# 'acc:%.4f p:%.4f r:%.4f F1:%.4f' % (acc, p, r, F1),'correct/sum:%d/%d, %.4f' % (correct, sum, correct / sum))if __name__ == '__main__':for epoch in range(n_epoch):train(epoch)eval(epoch)

如此,我们就完成了从原始数据制作dataset送入loader并且启动网络的所有代码。
等等,我们忘记了最重要的部分,我们没有定义网络的结构。
Net这里,这是一个继承自nn.Moudule的类,只要在这个类中定义网络的前向计算即可,反向计算会由pytorch自动实现。

为了简答起见,我们只举一个简单的例子,这个网络是随便写的,完全没有任何合理性的考虑,但至少能开始训练了

class Net(nn.Module):def __init__(self):super(Net, self).__init__()# 定义卷积层1self.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=4,  padding=3, dilation=1, groups=1, bias=True)# 最大池化层self.pool = nn.MaxPool2d(2, 2)#卷积层2self.conv2 = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)#全连接层self.fc1 = nn.Linear(64 * 16 * 16, 4096)self.fc2 = nn.Linear(4096, 1024)self.fc3 = nn.Linear(1024, 100)def forward(self, x):       # 重写forward函数,定义前向计算x = self.pool(F.relu(self.conv1(x)))    # 卷积->ReLU->池化x = self.pool(F.relu(self.conv2(x)))    # 卷积->ReLU->池化x = x.view(-1, 64 * 16 * 16)            # 将平面拉成一维向量x = F.relu(self.fc1(x))                 # 全连接->ReLUx = F.relu(self.fc2(x))                 # 全连接->ReLUx = self.fc3(x)                         # 全连接产生输出return x

这样,代码就完整了,运行开始以后我么你就恩能够看到训练正确率从0慢慢的向上爬。当然,这个网络是随意写的,性能肯定极其的差,但至少举了一个栗子。

我们都知道,深度学习也叫炼丹。所以接下来的活便是研究拜读各个大牛级炼丹师的的炼丹秘籍(论文),学习人家先进的炼丹手法(trick),把我们的栗子给炼成金丹。

五年炼丹,三年悟道,炼丹一道,非大毅力大智慧者不可成。吾等当昼夜苦修,方有机缘窥得一丝丹道真谛,与诸君共勉。

该代码的github地址https://github.com/Link2Link/TinyMind-start-with-0

如有疑问,请在github里提问

深度学习入门指南:从零开始TinyMind汉字书法识别相关推荐

  1. 【AI参赛经验】深度学习入门指南:从零开始TinyMind汉字书法识别——by:Link

    各位人工智能爱好者,大家好! 由TinyMind发起的#第一届汉字书法识别挑战赛#正在火热进行中,比赛才开始3周,已有数只黑马冲进榜单.目前TOP54全部为90分以上!可谓竞争激烈,高手如林.不是比赛 ...

  2. 基于PyTorch的TinyMind 汉字书法识别部分代码详解

    文章目录 0. 前言 1 遇到的问题 1.1 NameError: name 'cv2' is not defined 1.1.1 OpenCV下载 1.1.2 OpenCV安装 打开Anacoda3 ...

  3. 2023年的深度学习入门指南(10) - CUDA编程基础

    2023年的深度学习入门指南(10) - CUDA编程基础 上一篇我们走马观花地看了下SIMD和GPGPU的编程.不过线条太粗了,在开发大模型时遇到问题了肯定还会晕. 所以我们还是需要深入到CUDA中 ...

  4. 2023年的深度学习入门指南(14) - 不能只关注模型代码

    2023年的深度学习入门指南(14) - 不能只关注模型代码 最近,有一张大模型的发展树非常流行: 这个图是相当不错的,对于加深对于Transformer模型编码器.解码器作用的理解,模型的开源和闭源 ...

  5. 2023年的深度学习入门指南(1) - 从chatgpt入手

    2023年的深度学习入门指南(1) - 从chatgpt入手 2012年,加拿大多伦多大学的Hinton教授带领他的两个学生Alex和Ilya一起用AlexNet撞开了深度学习的大门,从此人类走入了深 ...

  6. 2023年的深度学习入门指南(5) - HuggingFace Transformers库

    2023年的深度学习入门指南(5) - HuggingFace Transformers库 这一节我们来学习下预训练模型的封装库,Hugging Face的Transformers库的使用.Huggi ...

  7. 2023年的深度学习入门指南(6) - 在你的电脑上运行大模型

    2023年的深度学习入门指南(6) - 在你的电脑上运行大模型 上一篇我们介绍了大模型的基础,自注意力机制以及其实现Transformer模块.因为Transformer被PyTorch和Tensor ...

  8. 2023年的深度学习入门指南(8) - 剪枝和量化

    2023年的深度学习入门指南(8) - 剪枝和量化 从这一节开始,我们要准备一些技术专项了.因为目前大模型技术还在快速更新迭代中,各种库和实现每天都在不停出现.因为变化快,所以难免会遇到一些问题.对于 ...

  9. TinyMind 汉字书法识别竞赛开启总决赛啦!!

    手写字体识别一直是人工智能领域一个热门研究方向,TinyMind联合书法领域的权威合作伙伴举办了一次汉字书法识别大赛,为广大人工智能和手写字体识别技术爱好者提供了一个练习和交流的机会. 竞赛开始后,高 ...

最新文章

  1. 计算各种形钢的重量用什么软件_造价常用工具不会用,30个常用工程算量工具免费送,速来领取收藏...
  2. 【阿里云课程】如何基于GAN完成人脸图像超分辨任务
  3. leetcode -- 357. Count Numbers with Unique Digits
  4. poj 2696 A Mysterious Function
  5. 数据结构 堆中的路径(最小堆)
  6. 调整idea中控制台及右侧提示框字体大小
  7. 磁盘IOPS计算与测量
  8. C语言中static的用法
  9. 关于MSHTML控件使用的问题
  10. 数学作图 网站 测试网站
  11. android rxbus工具类,RxBus的工具类
  12. 花都平安保险应该找谁?
  13. 【编程语言】面向对象的六大原则
  14. 利用IPv6的地址特性写一个攻击甩锅程序
  15. 如何注册和申请阿里云域名?
  16. 安卓webview长按分享,长按选择,长按复制,仿好奇心日报长按分享自定义弹窗的实现
  17. PPT制作三大技巧:图标 、图片背景透明和自动函数
  18. 一篇文章玩转 RNN 网络 原理
  19. 英语watch手表源自wacche
  20. 3DM视觉测量技术的应用及发展

热门文章

  1. 基于opencv实现人脸识别及签到系统
  2. Unity学习笔记 球形全景图平面像素坐标与三维坐标系上的坐标之间的转换
  3. 《东周列国志》第七十四回 囊瓦惧谤诛无极 要离贪名刺庆忌
  4. 车载网络结构(车内)-基础概念
  5. 写入iCloud在模拟器和真机上失败的解决办法
  6. Hashing(哈希)
  7. Java项目——云R记
  8. 【C++】C++基础语法
  9. 背景颜色渐变 background
  10. AToken全观:情人节妹子收了520个BTC,成吨狗粮灌到饱