网络程序设计课程总结
陆菁 SA16225200
项目介绍
基于深度学习神经网络等机器学习技术实现一个医学辅助诊断的专家系统原型,体现为对血常规检验报告的OCR识别,然后将识别的数据传入神经网络中预测年龄和性别。
项目要求
1.将血常规检验报告的图片识别出年龄、性别及血常规检验的各项数据,得到一个json数据存储到了mongodb数据库中,如识别出的结果与图片不一致,可人工修正。
2.搭建神经网络学习血常规检验的各项数据及对应的年龄性别,并且最后能根据血常规数据预测年龄和性别。
Pull Request
项目地址
项目实现
系统:ubuntu16.04 64位 语言:python2.7
1.依赖库的安装
# 安装numpy,
sudo apt-get install python-numpy # http://www.numpy.org/
# 安装opencv
sudo apt-get install python-opencv # http://opencv.org/
##安装OCR和预处理相关依赖
sudo apt-get install tesseract-ocr
sudo pip install pytesseract
sudo apt-get install python-tk
sudo pip install pillow
# 安装Flask框架、mongo
sudo pip install Flask
sudo apt-get install mongodb # 如果找不到可以先sudo apt-get update
sudo service mongodb started
sudo pip install pymongo
#安装keras
sudo pip install -U --pre theano
sudo pip install -U --pre keras
2.血常规图像识别
原始图片如上所示,首先对图像进行预处理,包括模糊等操作,然后通过canny边缘检测找到图上的三条黑色直线,并根据这三条直线进行透视变换,将有倾斜角度的照片变换到正面坐标系下,接着对图像进行裁剪,得到22个包含项目的小图片,最后通过Tesseract识别小图片得到结果。主要是在imageFilter.py中实现。下面是其中几个核心函数说明:
perspect(self, param=default):perspect函数用于透视image,他会缓存一个透视后的opencv numpy矩阵,并返回该矩阵,透视失败,则会返回None。
filter(self, param=default):filter函数返回img经过透视过后的PIL格式的Image对象,如果缓存中有PerspectivImg则直接使用,没有先进行透视,过滤失败则返回None
autocut(self, num, param=default):autocut函数用于剪切ImageFilter中的img成员,剪切之后临时图片保存在out_path,如果剪切失败,返回-1,成功返回0
ocr(self, num):ocr函数用于对img进行ocr识别,他会先进行剪切,之后进一步做ocr识别,返回一个json对象,如果剪切失败,则返回None
3.基于keras的年龄、性别预测
通过上一步得到训练样本和测试样本,如下图所示:
第一列表示性别,1为男性,0为女性,第二列为年龄。这两列当作标签数据,其他列则为要训练学习的数据。
通过解析这个csv文件,得到两个数组,X和Y。X为训练数据,要进行归一化,Y为标签,要转化为2进制矩阵。然后传入模型进行训练,以性别为例,模型定义如下:
model = Sequential()
model.add(Dense(32, input_shape=(22,)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(output_dim=32))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(output_dim=2))
model.add(Activation('softmax'))
一共定义了4层的神经网络,输入层、输出层、中间两层隐层。每个隐层都有32个神经元节点,采用relu作为激活函数。输出层采用softmax进行分类。
model.compile(loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy'])
模型最后用categorical_crossentropy作为损失函数,用RMSprop优化。最后定义了预测函数:
def sex_pred(X):
weights_file_path = "save_model/weights_gendar.hdf5"
model.load_weights(weights_file_path)
X/=255
pred_res = model.predict(X)
if np.argmax(pred_res[0]) == 0:
gendar = 0
else:
gendar = 1
return gendar
这个函数在view.py中predict()函数中调用,得到的结果用json封装传回前端页面进行显示。
@app.route("/predict", methods=['POST'])
def predict():
print ("predict now!")
data = json.loads(request.form.get('data'))
ss = data['value']
print ss
arr = numpy.array(ss)
arr = numpy.reshape(arr, [1, 22])
sex = sex_pred(arr)
age = age_pred(arr)
result = {
"sex":sex,
"age":int(age)
}
return json.dumps(result)
Demo演示
运行脚本:
python view.py
打开首页:
上传图片:
点击提交:
点击生成报告:
点击predict:
结果不太准,还需优化。
总结
在选这门课之前虽然了解课程和神经网络相关,比较难,但是由于自己对这方面挺感兴趣的,所以最后选了这课。但是在上这课之前并没有接触过python和机器学习,所以对整个项目贡献很少,大部分时间处于学习大神代码的阶段。这门课的上课方式也很独特,老师没有教具体内容,更多的是引导同学们完成项目,并组织同学们分享知识经验,这种方式的教学在学习上给了很大的自由,感觉比看书本念ppt更容易学到东西。像机器学习这种理论和实践结合密切的学科,光看公式算法是很难掌握的,而通过一个项目,自己动手实现却能很快的上手,并且在多人协作的方式下,根据同学们的分享,也能少走些弯路。
总的来说,在这个项目中学到的以下几点:
1.学习了python。python作为一种脚本语言在现在用处十分广泛,特别在科学计算方面功能十分强大,他的语法比C++和Java简单,往往通过几行代码可以实现C++几十行代码的功能。
2.学习了图像处理、机器学习相关知识。通过这段时间的学习,虽然仍然有很多知识没有弄懂,但是为以后的学习打下了基础。
3.对于团队协作有了新的认识。通过这种多人协作,能有效的推进项目进行,并且很容易发现自己的问题,例如当时pr的性别预测有个bug,训练集的正确率和验证集的正确率一直是1,但是第二天就被一个同学解决了,原因是没有归一化。
4.对于编程风格有了新的认识。在这种多人协作的模式中,命名规范和注释十分重要,有较好的命名和注释能有效的帮助别人了解你的工作,极大的促进项目推进。
总而言之,十分感谢孟老师的这门课,未来的学习道路还有很长!