使用TensorFlow的经验分享

2021-03-01 14:48:08 浏览数 (1)

前言:

本人是一个将要大学毕业的学生,目前就职在中世康恺的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》都是李金洪老师的书籍,上面不仅有知识点的讲解,还有大量可以实战的项目代码,训练数据等。

0 人点赞