前言:
本人是一个将要大学毕业的学生,目前就职在中世康恺的AI研发部门,中世康恺是一家服务于医学影像信息化的新型互联网公司,该公司以数字医疗影像为核心, 打造“云 集团 中心”模式。
入职3个月,从一个零基础的小白,到现在能够完成一个有关肺部CT的结节检测模型。这个过程是我成长很多。现打算将我的学习经历记录下来,提供给没学过这方面知识的朋友一个学习路线。目前我主要学习了模型的使用方法,在理论方面没有深入学习,之后打算进行理论方面的学习。
学习流程:
一、了解什么是机器视觉与神经网络
二、了解模型开发流程
三、搭建开发环境
四、了解卷积神经网络模型发展过程中的基本知识
五、学习Tf1.0与tf2.0
1. 学习创建数据集
2. 学习搭建模型
3. 学习训练模型
4. 学习模型保存、加载、预测
六、学习模型部署
七、项目实战遇到的问题
一、了解机器视觉
1. 什么是机器视觉
机器视觉就是对图形、视频等进行分类、识别、预测的判断,比如人脸识别、疾病诊断,图像处理等。
2. 如何实现机器视觉
目前我学的知识是用卷积神经网络实现机器视觉,搭建一个模型,将图片输入到模型内,模型将处理好的结果输出出来。
3. 什么是卷积神经网络
理论方面本人目前学习的不好,所以打个比喻,卷积神经网络就好像一个树状图,将数据从最左面的节点输入进去,节点与节点间有一个数字,数据与这个数字进行运算到下一个节点,以此往复直到最右面的节点,数据变成了一个新数据,新数据可能是一个数字代表类型或者结果,或者是一个二维数组代表一个处理好的图片,顺便一提多维的数组在机器学习中被称为张量(Tensor),整个树状图就是一个模型。
节点与节点间的数字被叫做权重,神经网络训练的过程就是调整这些数字的过程。
4. 神经网络的训练过程
1. 如何输入数据
刚才我们说把数据传进去,图片是如何传到模型中的那,首先我们知道图片是由像素点组成的,所以可以用二维数组去表示一个图片,二维数组中的每个位置是一个图片的像素点,将二维数组输入模型即可。
2. 如何训练模型
刚才我们说要调整模型中的权重,如何调整个权重那,我们需要了解一下正向传播与反向传播。正向传播就是将这个图片与节点间的权重计算后生成结果。反向传播就是根据正向传播生成的结果,去修改节点间的数字。
举个例子,比如有100张图片,其中20张是狗,在正向传播处理完100张图片后发现准确率是百分之10,反向传播修改了模型的权重,再次正向传播发现准确率上升了,说明权重的调整是正确的。
反向传播时每个权重如何调整涉及到反向链式求导,这个我目前没有好好了解先不描述。
5. 卷积神经网络的原理
一定有人很多好奇为什么模型训练后可以去识别图片那,目前我不知道,现在理论学的不好,之后进行理论的学习。
二、了解模型的开发流程
我目前将开发流程分成了7个阶段。
1. 数据收集:
作用:收集我们需要的图片,处理数据的一些问题。
2. 模型创建:
作用:创建模型的结构。
3.编译模型:
作用:设置模型的参数,比如优化器、损失函数、学习率。
4. 数据集创建:
作用:将数据集中到一起分成训练集和测试集供模型训练。
5. 模型训练:
作用:将数据输入到模型中,模型去调整权重。在回调函数中设置,训练次数、输出路径。
6. 模型保存:
作用:将训练好的模型保存起来。
7. 模型部署:
作用:将保存的模型部署到服务器或本地以便提供使用。
三、搭建开发环境
目前我学习的是Anaconda tensorflow。
1. 下载Anaconda
从Anaconda官网下载Anaconda开发工具,选择对应的版本
2. 搭建python虚环境
建议在虚环境中操作,这样出现无法调整的问题,直接删除虚环境即可,而且多个虚环境还可用多个tensorflow版本,不会出现冲突。
目前下载的Anaconda自带python为3.8,通过conda下载tensorflow2.3.0后可能无法使用gpu训练,除非自己使用pip下载tensorflow与CUDA,建议虚环境使用python3.7,tensorflow使用tensorflow2.1.0。
3. 下载tensorflow
直接在Anaconda中选择建好的python3.7虚环境,之后再选择tensorflow-gpu即可。
四、 从模型发展中学习基础知识
1. 1994年LeNet模型
这是卷积神经网络(CNN)的第一个模型,定义了基本的网络结构(输入层、卷积层(conv)、池化层(pool)、激活函数、全连接层(fc)、损失函数、输出层)
1.什么是卷积
2.什么是池化
3.什么是激活函数
4.什么是全连接层
5.什么是损失函数
2. 2012年AlexNet模型
在LeNet的基础上,AlexNet模型共包括5层卷积与三层全连接,层数上加深到8层。采用dropout去解决过拟合问题。提出了局部响应归一化(LRN)。采用ReLU激活函数替代Sigmoid激活函数加快SGD收敛速度。
1. 什么是dropout
2. 什么是LRN
3. 什么是Relu、Sigmoid
5. 什么是过拟合
6. 为什么Relu比Sigmoid让模型收敛快
7. 为什么网络深度越深能提高准确率
3. 2014年VGG模型
VGG模型用3x3卷积核替代了之前模型中的大卷积核、采用更小的步长、用1x1卷积核替代全连接层增加网络的非线性表达能力,层数上加深到19层
1. 为什么3x3卷积核比大卷积核效果好
2. 1x1卷积核为什么能增加非线性表达能力
4. 2014年GoogLeNet模型
随着网络的加深会造成梯度爆炸和梯度消失的问题,GoogLeNet引入Inception结构增加模型的宽度来提高模型的性能,使用批量归一化(BN)去替代LRN解决梯度消失的问题,层数上升到22层
1. 什么是Inception结构
2. 什么是批量归一化(BN)
3. 什么是梯度消失
4. 什么是梯度爆炸
5. 2015年ResNet模型
在上百的网络中BN并不能完全解决梯度消失问题,ResNet开始使用残差网络技术,解决反向传播时梯度消失的问题,层数大大加深到152层。
1. 什么是残差网络技术
6. 2017年DenseNet模型
DenseNet脱离了加深网络层数(ResNet)和加宽网络结构(Inception)来提升网络性能的定式思维,从特征的角度考虑,通过特征重用和旁路(Bypass)设置,既大幅度减少了网络的参数量,又在一定程度上缓解了梯度消失问题的产生
五、学习Tensorflow1.0与tensorflow2.0
1. 什么是tensorflow
一个核心开源库,可以帮助您开发和训练机器学习模型。,Tf1.0主要采用静态计算图,tf2.0主要采用动态计算图
2. 从哪个开始学习
个人建议直接tf2.0学起,2.0的很多代码都比较简洁,比如训练模型,保存模型,加载模型之类的非常方便,上手比较快。遇到1.0的代码可以用2.0自带的代码转换,将1.0代码转为2.0代码使用。
3.学习tf中的各种库
1. 学习创建数据集
1.创建数据集学习:tf.data.Dataset库
2.处理数据集的数据:map
3.设置数据批次:test_dataset.batch
4.打乱数据:dataset.shuffle
2. 学习搭建模型
1.模型的层的搭建学习:tensorflow.keras.layers库
2.设置优化器学习:tensorflow.keras.optimizers库
3.构建模型学习:tensorflow.keras.models库
3.编译模型:model.compile
3. 学习训练模型
1.了解fit函数的参数作用
2.设置回调函数学习:tensorflow.keras.callbacks库
3.模型损失率与准确率可视化
4. 学习模型保存、加载、预测
1.保存h5模型、pb模型:学习model.save
2.加载h5模型、pb模型:学习model.load
3.使用模型进行预测:学习model. predict
六、学习模型部署
1. 服务器安装docker
2. TF_Serving镜像下载
3. pb模型部署
4. 使用模型接口
七、项目实战的问题
数据预处理:
1. gdcm找不到问题
2. 数据量过大导致的oom问题
数据集创建:
3. 数据量过大导致的数据集创建失败问题
4. as_list()形状问题
5. map中的内存不足问题。
模型训练:
6. 模型二次运行失败问题
7. TF无法GPU训练问题
模型保存:
8. 回调函数保存模型时的路径问题、
9. pb文件保存后加载问题
模型部署问题:
10. TFServing部署位置错误问题
问题一: GDCM找不到问题
产生原因:
开始时,我先对数据进行预处理,但有一部分图片是压缩的dcm图片,需要用gdcm库去处理,pip下载了第三方库,却显示找不到。
解决办法:
在网上搜索“GDCM-3.0.8-Windows-x86_64.exe”后下载,在安装时选择添加环境变量的选项,安装结束之后便可以找到这个库。如果安装时报错可以去下载一个“微软常用运行库合集 64位”试一下。
问题二: 数据量过大导致的oom问题
产生原因:
第三方库安装好后,开始进行预处理,但我没有考虑数据量的问题,打算将每张dcm图片预处理后添加到一个全局的列表中,最后保存成一个npy文件。但是由于列表存的内容过多导致内存溢出。
解决办法:
在保存时,以每张图片单独保存成一个npy文件。这样列表就一直只保存一个图片大小的信息。
问题三: 数据量过大导致的数据集创建失败问题
产生原因:
处理完数据后,开始创建数据集,还是数据量过大所以当全部的np文件添加到数据集中时出现了内存不足的报错。
解决办法:
1. 将文件名保存到数据集中,在需要训练时再动态加载,这里采用了map函数。
2. map中没有加载npy文件的原生方法,而传递的参数为张量不能直接使用np.load进行加载,这里需要使用tf.py_function(函数名,张量,形状)函数,在这个函数中可以按照pythob原生的方法处理数据,解决tf中没有npy加载方法的问题。
问题四: as_list()形状问题
出现原因:
采用动态加载npy文件的方法后,训练时出现了“as_list() is not defind on an unknown TensorShape”这个问题。加载的数据形状是正确的不过还是报错。
解决办法:
用tf.reshape()指定数据的形状。
参考代码:
代码语言:javascript复制def _parseone(filename, labelname):
def returndata(filename,labelname):
data = np.load(filename.numpy().decode('utf-8') ).reshape(512,512,1)
if labelname == '':
lab = np.zeros((512,512)).reshape(512,512,1)
else:
lab = np.load(labelname.numpy().decode('utf-8')).reshape(512,512,1)
return data,lab
data ,lab = tf.py_function( returndata,[filename,labelname],[tf.float64,tf.float64])
return tf.reshape(data,[512,512,1]) ,tf.reshape(lab,[512,512,1])
# 加载图片
traindataset = traindataset.map(_parseone)
问题五: map中的内存不足问题
出现原因:
在map中使用py_func加载npy文件时,训练一小会后,我发现会出现“”显示内存不足。在上段代码中,如果labelname是空数据,会生成一个(512,512,1)的np文件。
错误原因是“np.zeros((512,512)).reshape(512,512,1)” 生成的np文件内存一直不会释放。
解决办法:
将np文件变成全局变量,每次labelname直接等于这个全局变量,防止多次生成新数据。
修改代码后内存够用,但依然达到百分之90左右,单次训练训练后内存会下降,我怀疑np.load加载的内存,在单次结束前不会释放。所以本文py_func方法代码仍需改进。
问题六: 模型二次运行失败问题
出现原因:
在Spyder中使用代码训练时,有一次修改批次大小于是手动停止了运行,当再次运行时,提醒显存不足,我查看后发现,程序停止后显存并没有释放。
解决办法:
停止模型时不要去选择停止,直接关闭右侧的Console,显存会自动清楚,使用新生成的Console即可。
实例图片:
问题七: TF无法使用GPU训练问题
出现原因:
在模型训练时训练过慢,发现时使用cpu进行运算,而不是gpu。后来发现tf2.3-gpu我无法使用gpu运算。不知道什么原因。
解决办法:
将python改为3.7,tf降为2.1。
问题八:回调函数的模型路径问题
出现原因:
在模型第一次训练结束后,回调函数保存模型时,出现异常“AttributeError: 'WindowsPath' object has no attribute 'format'”,原因是回调函数的模型保存位置要用字符串不能用其他格式。
解决办法:
将Path的路径转为str即可。
问题九:pb文件保存后加载问题
出现原因:
在模型训练结束后,我打算将h5文件转为pb文件,进行模型的部署,转换后我打算加载pb文件测试是否能使用。结果出现“ValueError: Unknown loss function:dice_coef_loss”。
解决办法:
1. 当保存模型时,将include_optimizer设为False,不带优化器即可。model.save(pb_path,include_optimizer=False)保存模型。
2. tf.keras.models.load_model(PATH,custom_objects={})加载模型,如果加载成功直接部署即可。
3. 如果加载模型后需要预测,需重新编译模型,将优化器加到模型中。
问题十:TFServing部署位置错误问题
出现原因:
服务器部署模型时,一直显示找不到模型。
解决办法:
模型必须放到TFServing的models文件夹下才能被识别到,如果有多个模型,文件夹使用数字,会选择数字最大的作为使用的模型。
感言:
学习这方面知识不能只靠在书本上去看,需要动手亲自去实现每一个步骤,理解每一段代码的意思,这里推荐一下我学习时的书籍,入门python的书《python带我起飞》,入门机器视觉的书《机器视觉之TensorFlow2》都是李金洪老师的书籍,上面不仅有知识点的讲解,还有大量可以实战的项目代码,训练数据等。