网络程序设计课程学习心得总结

来源:互联网 发布:淘宝联盟互刷 编辑:程序博客网 时间:2024/04/25 19:19


作者:王孟之    学号:SA16225307

网络程序设计,听起来像搞计算机网络的,如果是这样,我不会选这门课,这门课其实是研究神经网络的,这玩意火啊,2016年被誉为人工智能的元年,三月份AlphaGo与李世石的围棋大战我局局都看,也让我第一次了解到深度学习,神经网络等新鲜又高大上的名词。我本科毕业设计做的是一个五子棋程序,利用极大极小博弈树加AlphaBeta剪枝就取得了不错的效果,但还是打不过一些厉害的五子棋程序,当时我就想要研究下这个神经网络,把它集成到自己的五子棋程序里,有了自主学习能力的五子棋程序,岂不打遍天下无敌手?
正因为想研究深度学习方面的内容,我选的工程实践项目是基于深度学习的图像验证码识别,本来老师指定的深度学习平台是TensorFlow,但有另一组同学也选了这个项目,如果都一样的话,感觉没什么意思,我在孟老师的网站上看到了百度开源深度学习平台这个东西,才知道原来百度在深度学习上也有研究,用本国的东西是不是比用被墙了的谷歌的东西方便?
这门课的第一次实验就是做一个OCR手写字符识别系统,正中下怀,这玩意我早在PaddlePaddle上实现了,其实只要改demo里的几个参数就行了。具体项目信息如下。


项目地址:https://coding.net/u/wangmengzhi/p/np2016


项目A1:神经网络实现手写字符识别系统

  • BP神经网络
  • 输入层维数 400
  • 隐藏层神经元 15
  • 输出层维数 10
  • 学习率 0.1
  • 激活函数 sigmoid
  • 参数保存在 nn.json

环境配置(如果在本地运行)

  • 系统: ubuntu 14.04 64位
# 安装pip
sudo apt-get install python-pip
# 用pip安装numpy和scipy, 使用科大镜像加速
pip install --user numpy scipy -i https://pypi.mirrors.ustc.edu.cn/simple
# 如果上一步安装失败就使用ubuntu的包管理器试试
sudo apt-get install python-numpy python-scipy
# 安装sklearn, neural_network_design.py需要调用它做交叉验证
pip install -U scikit-learn -i https://pypi.mirrors.ustc.edu.cn/simple
# 如果在服务器上运行,修改ocr.js里的HOST为服务器的地址,如http://2016.mc2lab.com

运行

1.    下载图像和标签数据

2.   wget http://labfile.oss.aliyuncs.com/courses/593/data.csv
3.   wget http://labfile.oss.aliyuncs.com/courses/593/dataLabels.csv

4.    训练模型

5.   pythonneural_network_design.py

6.    创建服务器

7.   python -m SimpleHTTPServer 3000

8.    加载服务器

9.   pythonserver.py

10.访问

11. localhost:3000
  • 实现指导见https://www.shiyanlou.com/courses/593

Demo

项目A2:血常规检验报告OCR

运行环境

# 安装numpy,
sudo apt-get install python-numpy # http://www.numpy.org/
# 安装opencv
sudo apt-getinstall python-opencv # http://opencv.org/
##安装OCR和预处理相关依赖
sudo apt-getinstall tesseract-ocr
sudo pip install pytesseract
sudo apt-getinstall 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

运行

cd  BloodTestReportOCR
python view.py # upload图像,在浏览器打开http://yourip:8080

view.py

Web 端上传图片到服务器,存入mongodb并获取oid,稍作修整,希望能往REST架构设计,目前还不完善; 前端采用了vue.js, mvvm模式。写了两个版本,一个是index.html无插件,另一个使用了bootstrap-fileinput插件,有点问题;

imageFilter.py

对图像透视裁剪和OCR进行了简单的封装,以便于模块间的交互,规定适当的接口

    imageFilter = ImageFilter() # 可以传入一个opencv格式打开的图片
    num = 22
    print imageFilter.ocr(num)

ocr函数 - 模块主函数返回识别数据

用于对img进行ocr识别,他会先进行剪切,之后进一步做ocr识别,返回一个json对象 如果剪切失败,则返回None @num 规定剪切项目数

perspect函数做 - 初步的矫正图片

用于透视image,他会缓存一个透视后的opencv numpy矩阵,并返回该矩阵 透视失败,则会返回None,并打印不是报告 @param 透视参数

  • 关于param

参数的形式为[p1, p2, p3 ,p4 ,p5]。 p1,p2,p3,p4,p5都是整型,其中p1必须是奇数。

p1是高斯模糊的参数,p2和p3是canny边缘检测的高低阈值,p4和p5是和筛选有关的乘数。

如果化验报告单放在桌子上时,有的边缘会稍微翘起,产生比较明显的阴影,这种阴影有可能被识别出来,导致定位失败。 解决的方法是调整p2和p3,来将阴影线筛选掉。但是如果将p2和p3调的比较高,就会导致其他图里的黑线也被筛选掉了。 参数的选择是一个问题。 我在getinfo.default中设置的是一个较低的阈值,p2=70,p3=30,这个阈值不会屏蔽阴影线。 如果改为p2=70,p3=50则可以屏蔽,但是会导致其他图片识别困难。

就现在来看,得到较好结果的前提主要有三个

  • 化验单尽量平整
  • 图片中应该包含全部的三条黑线
  • 图片尽量不要包含化验单的边缘,如果有的话,请尽量避开有阴影的边缘。

filter函数 - 过滤掉不合格的或非报告图片

返回img经过透视过后的PIL格式的Image对象,如果缓存中有PerspectivImg则直接使用,没有先进行透视 过滤失败则返回None @param filter参数

autocut函数 - 将图片中性别、年龄、日期和各项目名称数据分别剪切出来

用于剪切ImageFilter中的img成员,剪切之后临时图片保存在out_path, 如果剪切失败,返回-1,成功返回0 @num 剪切项目数 @param 剪切参数

剪切出来的图片在BloodTestReportOCR/temp_pics/ 文件夹下

函数输出为data0.jpg,data1.jpg......等一系列图片,分别是白细胞计数,中性粒细胞记数等的数值的图片。

classifier.py

用于判定裁剪矫正后的报告和裁剪出检测项目的编号

imgproc.py

将识别的图像进行处理二值化等操作,提高识别率 包括对中文和数字的处理

digits

将该文件替换Tesseract-OCR\tessdata\configs中的digits

项目A3:PaddlePaddle MNIST demo & 预测年龄性别

安装PaddlePaddle

# 下载安装包
wget https://github.com/PaddlePaddle/Paddle/releases/download/V0.8.0b1/paddle-cpu-0.8.0b1-Linux.deb
# 安装
gdebi paddle-cpu-0.8.0b1-Linux.deb
如果 gdebi 没有安装,则需要使用 sudo apt-get install gdebi, 来安装 gdebi 
或者使用下面一条命令安装.
dpkg -i paddle-cpu-0.8.0b1-Linux.deb
apt-getinstall -f
在 dpkg -i的时候如果报一些依赖未找到的错误是正常的, 在 apt-getinstall -f里会继续安装 PaddlePaddle
官方教程http://www.paddlepaddle.org/doc_cn/build_and_install/install/ubuntu_install.html

下载MNIST数据集

下载地址https://pan.baidu.com/s/1kUNBkyz

在当前目录建立data文件夹,将MNIST.rar里的train和test文件夹解压到data文件夹下

注该数据集将原版MNIST二进制文件中的图片提取出来分别放入train和test文件夹,用户可以自行添加图片到train和test文件夹下,但要修改源码中关于图像大小的参数

训练MNIST

shpreprocess.sh # 调用preprocess.py预处理
shtrain.sh # 调用vgg.py训练,该脚本文件可设置训练模型存放路径和训练线程数等参数
pythonprediction.py # 预测,注意设置其中模型路径model_path

训练性别

训练前把train.csv,predict.csv拷贝到当前路径

shtrain_sex.sh # 调用trainer_config_sex.py训练,注意设置num_passes训练次数,训练三十次错误率能降到30%左右
shpredict_sex.sh # 调用trainer_config_sex.py预测,注意设置模型路径model_path

训练年龄

训练前把train.csv,predict.csv拷贝到当前路径

sh train_age.sh # 调用trainer_config_age.py训练,注意设置num_passes训练次数,如果以5分段预测,训练100次错误率在85%左右,不分段错误率在95%左右
sh predict_age.sh # 调用trainer_config_age.py预测,注意设置模型路径model_path

preprocess.py

预处理模块,将data文件夹下的图片转换为PaddlePaddle格式

转换后的数据存放在data/batches文件夹下

vgg.py

训练模块,使用VGG网络训练,该网络在ILSVRC2014的图像分类项目上获第二名

训练后的模型存放在vgg_model/pass-n文件夹下,n表示第几次训练,每训练一次会生成一个模型文件夹,理论上训练次数越多的模型效果越好

注使用CPU训练速度很慢,平均训练一次需要近半小时,目前PaddlePaddle使用CPU训练出来的模型和GPU训练出来的模型不一样,所以用CPU训练只能用CPU预测,用GPU训练只能用GPU预测,而且用GPU预测要安装GPU版的PaddlePaddle和CUDA,cudnn,并且需要NVIDIA显卡支持,所以这里用的是CPU版的

prediction.py

预测模块,其中image参数为要识别的图像路径

dataprovider.py

实现向PaddlePaddle提供数据的接口,详见dataprovider.py注释

trainer_config_sex.py

性别训练网络配置

trainer_config_age.py

年龄训练网络配置

predict_age.sh & predict_sex.sh

预测脚本文件,预测的结果保存在当前路径下的result.txt文件,第一个数为预测的结果,后面的数是每个标签的概率

prediction_age.py & prediction_sex.py

提供预测接口,也可单独执行,接口输入为一个形如[[[0,1,2,...]]]的list,输出为性别或年龄的标签

train.list & test.list

训练文件和测试文件的列表

init.py

使A2的文件能导入本文件夹下的模块

Demo


关于PR

#14 fix bug(接受)

https://coding.net/u/mengning/p/np2016/git/pull/14

       修复了服务器端只监听localhost的bug,将DigitRecogn/server.py中的HOST_NAME = 'localhost'改为HOST_NAME = ''

 

#38 ocr(接受)

https://coding.net/u/mengning/p/np2016/git/pull/38

       用tesseract将temp_pics文件夹下的图片识别到temp_nums文件夹下

BloodTestReportOCR/ocr.py

input_path='temp_pics'output_path='temp_nums'ifnot(os.path.exists(output_path)):    os.makedirs(output_path)# 遍历input_path下所有后缀为jpg的图片for i inos.listdir(input_path):    if os.path.splitext(i)[1] == '.jpg':       image = Image.open(input_path+'/'+i)        num =pytesseract.image_to_string(image,None,False,'-psm 7 digits') #-psm 7 digits表示识别一行数字        if(num!=''):            print i+'\t'+num            output =open(output_path+'/'+os.path.splitext(i)[0]+'.txt', 'w')            output.write(num)            output.close()

#65 添加中文OCR(拒绝)

https://coding.net/u/mengning/p/np2016/git/pull/65

       添加识别姓名,日期,数据标签,但由于识别率较低,放弃使用OCR方式识别项目名称。

 

#117 PaddlePaddle MNIST Demo(接受)

https://coding.net/u/mengning/p/np2016/git/pull/117


       PaddlePaddle/image_provider.py(向PaddlePaddle提供数据)

def hook(settings, img_size, mean_img_size,num_classes, color, meta, use_jpeg,        is_train, **kwargs):   settings.mean_img_size = mean_img_size   settings.img_size = img_size   settings.num_classes = num_classes   settings.color = color   settings.is_train = is_train   if settings.color:       settings.img_raw_size = settings.img_size * settings.img_size * 3   else:       settings.img_raw_size = settings.img_size * settings.img_size   settings.meta_path = meta   settings.use_jpeg = use_jpeg   settings.img_mean = image_util.load_meta(settings.meta_path,                                            settings.mean_img_size,                                            settings.img_size,                                            settings.color)   settings.logger.info('Image size: %s', settings.img_size)   settings.logger.info('Meta path: %s', settings.meta_path)   settings.input_types = [       dense_vector(settings.img_raw_size), # image feature       integer_value(settings.num_classes)] # labels   settings.logger.info('DataProvider Initialization finished')@provider(init_hook=hook)def processData(settings, file_name):   """    加载数据    迭代每一批的所有图像和标签   file_name: 批文件名   """    #使用pickle类来进行python对象的序列化,而cPickle提供了一个更快速简单的接口,如python文档所说的:“cPickle -- A faster pickle”   data = cPickle.load(io.open(file_name, 'rb'))   indexes = list(range(len(data['images'])))   if settings.is_train:       random.shuffle(indexes)   for i in indexes:       if settings.use_jpeg == 1:           img = image_util.decode_jpeg(data['images'][i])       else:           img = data['images'][i]       #如果不是训练, 裁剪图像中心区域.否则随机裁剪,       img_feat = image_util.preprocess_img(img, settings.img_mean,                                            settings.img_size, settings.is_train,                                            settings.color)       label = data['labels'][i]       yield img_feat.tolist(), int(label)

PaddlePaddle/preprocess.py(将图片转为PaddlePaddle格式)

#处理命令行参数defoption_parser():    parser = OptionParser(usage="usage:python preprcoess.py "\                          "-i data_dir[options]")    parser.add_option("-i","--input", action="store",                      dest="input",help="图片路径")    parser.add_option("-s","--size", action="store",                      dest="size",help="图片大小")    parser.add_option("-c","--color", action="store",                      dest="color",help="图片有没有颜色")    return parser.parse_args()if __name__ =='__main__':     options, args = option_parser()     data_dir = options.input     processed_image_size = int(options.size)     color = options.color == "1"     data_creator =ImageClassificationDatasetCreater(data_dir,                                                     processed_image_size,                                                     color)     #每个训练文件包含的图片数     data_creator.num_per_batch = 1000     data_creator.overwrite = True     data_creator.create_batches()

PaddlePaddle/vgg.py(网络配置文件)

is_predict =get_config_arg("is_predict", bool, False)####################DataConfiguration ##################if notis_predict:  data_dir='data/batches/'  meta_path=data_dir+'batches.meta'  '''  mean_img_size,img_size图像大小  num_classes分类类别数  color图像有无颜色  '''  args = {'meta':meta_path,'mean_img_size': 28,          'img_size': 28,'num_classes': 10,          'use_jpeg': 1,'color': 0}  #引用image_provider.py中的processData函数 define_py_data_sources2(train_list=data_dir+"train.list",                          test_list=data_dir+'test.list',                         module='image_provider',                          obj='processData',                          args=args)######################AlgorithmConfiguration #############settings(    #批尺寸,一次训练多少数据    batch_size = 128,    #学习速率    learning_rate = 0.1 / 128.    learning_method = MomentumOptimizer(0.9),    #权重衰减,防过拟合    regularization = L2Regularization(0.0005 *128))#######################NetworkConfiguration ##############图片大小,通道数×长×宽data_size=1*28*28#分类数量label_size=10img =data_layer(name='image',                 size=data_size)#small_vgg在trainer_config_helpers.network预定义predict =small_vgg(input_image=img,                    num_channels=1,#图像通道数,灰度图像为1                    num_classes=label_size)if notis_predict:    lbl = data_layer(name="label",size=label_size)    outputs(classification_cost(input=predict,label=lbl))else:    #预测网络直接输出最后一层的结果而不是像训练时以cost layer作为输出    outputs(predict)

PaddlePaddle/prediction.py(预测文件)

classImageClassifier():    def __init__(self,                 train_conf,                 use_gpu=True,                 model_dir=None,                 resize_dim=None,                 crop_dim=None,                 mean_file=None,                 oversample=False,                 is_color=False):        """        train_conf: 网络配置文件        model_dir: 模型路径        resize_dim: 设为原图大小        crop_dim: 图像裁剪大小,一般设为原图大小        oversample: bool, oversample表示多次裁剪,这里禁用        """        self.train_conf = train_conf        self.model_dir = model_dir        if model_dir is None:            self.model_dir =os.path.dirname(train_conf)        self.resize_dim = resize_dim        self.crop_dims = [crop_dim, crop_dim]        self.oversample = oversample        self.is_color = is_color        self.transformer =image_util.ImageTransformer(is_color = is_color)        self.transformer.set_transpose((2,0,1))        self.mean_file = mean_file        mean = np.load(self.mean_file)['data_mean']        mean = mean.reshape(1,self.crop_dims[0], self.crop_dims[1])        self.transformer.set_mean(mean) # meanpixel        gpu = 1 if use_gpu else 0        conf_args ="is_test=1,use_gpu=%d,is_predict=1" % (gpu)       #使用parse_config() 解析训练时的配置文件        conf = parse_config(train_conf,conf_args)       swig_paddle.initPaddle("--use_gpu=%d" % (int(use_gpu)))        self.network =swig_paddle.GradientMachine.createFromConfigProto(conf.model_config)        assert isinstance(self.network,swig_paddle.GradientMachine)       #从模型文件加载参数        self.network.loadParameters(self.model_dir)        data_size = 1 * self.crop_dims[0] *self.crop_dims[1]        slots = [dense_vector(data_size)]        self.converter =DataProviderConverter(slots)    def get_data(self, img_path):        """        1. 读取图片.        2. resize 或oversampling.        3. transformer data: transpose, submean.        return K x H x W ndarray.        """        image = image_util.load_image(img_path,self.is_color)        if self.oversample:            # image_util.resize_image: shortside is self.resize_dim            image =image_util.resize_image(image, self.resize_dim)            image = np.array(image)            input = np.zeros((1,image.shape[0], image.shape[1],1),                             dtype=np.float32)          if self.is_color:                   input[0]= image.astype(np.float32)          else:                 for i inrange(0,self.resize_dim):                 for j in range(0,self.resize_dim):                      input[0][i][j][0]=image[i][j]            input =image_util.oversample(input, self.crop_dims)        else:            image =image.resize(self.crop_dims, Image.ANTIALIAS)          image = np.array(image)            input = np.zeros((1,self.crop_dims[0], self.crop_dims[1],1),                             dtype=np.float32)          if self.is_color:                   input[0]= image.astype(np.float32)          else:                 for i inrange(0,self.resize_dim):                 for j in range(0,self.resize_dim):                      input[0][i][j][0]=image[i][j]        data_in = []        for img in input:            img = self.transformer.transformer(img).flatten()            data_in.append([img.tolist()])        return data_in    def forward(self, input_data):        in_arg = self.converter(input_data)        return self.network.forwardTest(in_arg)    def forward(self, data, output_layer):        #返回每种标签的概率        input = self.converter(data)        self.network.forwardTest(input)        output =self.network.getLayerOutputs(output_layer)        return output[output_layer].mean(0)    def predict(self, image=None,output_layer=None):        assert isinstance(image, basestring)        assert isinstance(output_layer,basestring)        data = self.get_data(image)#读取图片        prob = self.forward(data, output_layer)        lab = np.argsort(-prob)#按降序排列,返回的是数组值的索引值        logging.info("Label of %s is:%d", image, lab[0])if __name__ =='__main__':    image_size=28#图像大小    crop_size=28#图像大小    multi_crop=0#多次裁剪    config="vgg.py"#网络配置文件    output_layer="__fc_layer_1__"    mean_path="data/batches/batches.meta"    model_path="vgg_model/pass-00000/"#模型路径    image="test.bmp"#要识别的图片路径    use_gpu=0#是否使用GPU    obj = ImageClassifier(train_conf=config,                          model_dir=model_path,                         resize_dim=image_size,                          crop_dim=crop_size,                          mean_file=mean_path,                          use_gpu=use_gpu,                         oversample=multi_crop)    obj.predict(image, output_layer)

这里使用的是16层的VGG网络,结构如下:

 

#191 PaddlePaddle预测年龄性别(接受)

https://coding.net/u/mengning/p/np2016/git/pull/191

       添加了两个网络分别预测年龄和性别,在只使用一个全连接层的情况下,训练三十次可将性别预测的错误率降到30%左右;在将年龄以5分段的情况下(0-99分为0-4,5-9……),训练100次的错误率在85%左右,不分段的错误率在95%左右。

       PaddlePaddle/dataprovider.py添加如下代码:

@provider(input_types=[    #训练数据大小   dense_vector(26),    #标签种类   integer_value(2)])#提供性别训练数据的函数def process_sex(settings, file_name):   csvfile = file('train.csv', 'rb')   reader = csv.reader(csvfile)   for row in reader:       if row[0]!='id':           sex=0           if(row[1]=='\xc4\xd0'):              sex=1           del row[0]           del row[0]           del row[0]           pixels = []           for j in row:              if(j!=''):                      pixels.append(float(j))           if(len(pixels)==26):                  yieldpixels,int(sex)   csvfile.close()def predict_initializer(settings,**kwargs):   settings.input_types=[   dense_vector(26)    ]#提供性别预测数据的函数@provider(init_hook=predict_initializer,should_shuffle=False)def process_predict_sex(settings,file_name):   csvfile = file('predict.csv', 'rb')   reader = csv.reader(csvfile)   rows= [row for row in reader]    #预测第一行   row=rows[1]   sex='女'   if(row[1]=='\xc4\xd0'):       sex='男'   print '实际性别:'+sex   del row[0]   del row[0]   del row[0]   pixels = []   for j in row:       pixels.append(float(j))   if(len(pixels)==26):       yieldpixels@provider(input_types=[   dense_vector(26),   integer_value(100)])#提供年龄训练数据的函数def process_age(settings, file_name):   csvfile = file('train.csv', 'rb')   reader = csv.reader(csvfile)   for row in reader:       if row[0]!='id':           age=int(row[2])           del row[0]           del row[0]           del row[0]           pixels = []           for j in row:              if(j!=''):                      pixels.append(float(j))           if(len(pixels)==26):                  yieldpixels,age   csvfile.close()def predict_initializer(settings,**kwargs):   settings.input_types=[   dense_vector(26)    ]#提供年龄预测数据的函数@provider(init_hook=predict_initializer,should_shuffle=False)def process_predict_age(settings,file_name):   csvfile = file('predict.csv', 'rb')   reader = csv.reader(csvfile)   rows= [row for row in reader]   row=rows[1]   print '实际年龄:'+row[2]   del row[0]   del row[0]   del row[0]   pixels = []   for j in row:       if(j!=''):           pixels.append(float(j))   if(len(pixels)==26):       yieldpixelscsvfile.close()

PaddlePaddle/trainer_config_age.py

is_predict =get_config_arg('is_predict', bool, False)define_py_data_sources2(    #训练文件列表    train_list='train.list' if not is_predictelse None,    #测试文件列表    test_list='test.list',    #指明提供数据的函数    module="dataprovider",    obj='process_age' if not is_predict else'process_predict_age')settings(    #批尺寸    batch_size=128 if not is_predict else 1,    #学习速率    learning_rate=2e-3,    #学习方式    learning_method=AdamOptimizer(),    #权重衰减    regularization=L2Regularization(8e-4))#输入数据大小data =data_layer(name="data", size=26)#直接全连接,指明输出数据大小,激活函数是Softmaxoutput =fc_layer(input=data, size=100, act=SoftmaxActivation())if is_predict:    #获得最大概率的标签    maxid = maxid_layer(output)    outputs([maxid, output])else:    #标签大小    label = data_layer(name="label",size=100)    #计算误差    cls = classification_cost(input=output,label=label)    outputs(cls)

PaddlePaddle/trainer_config_sex.py

is_predict =get_config_arg('is_predict', bool, False)define_py_data_sources2(    #训练文件列表    train_list='train.list' if not is_predictelse None,    #测试文件列表    test_list='test.list',    #指明提供数据的函数    module="dataprovider",    obj='process_sex' if not is_predict else'process_predict_sex')settings(    #批尺寸    batch_size=128 if not is_predict else 1,    #学习速率    learning_rate=2e-3,    #学习方式    learning_method=AdamOptimizer(),    #权重衰减    regularization=L2Regularization(8e-4))#输入数据大小data =data_layer(name="data", size=26)#直接全连接,指明输出数据大小,激活函数是Softmaxoutput =fc_layer(input=data, size=2, act=SoftmaxActivation())if is_predict:    #找出最大概率的标签    maxid = maxid_layer(output)    outputs([maxid, output])else:    #标签大小    label = data_layer(name="label",size=2)    #计算误差    cls = classification_cost(input=output,label=label)    outputs(cls)

#247 将PaddlePaddle预测与A2整合(未处理)

https://coding.net/u/mengning/p/np2016/git/pull/247

       参考其他同学的pr,在index.html中添加了predict_pd按钮,PaddlePaddle文件夹下的空文件__init__.py使BloodTestReportOCR文件夹下的view.py能导入PaddlePaddle文件夹下的预测接口模块prediction_age.py和prediction_sex.py进行预测,这两个模块也可单独执行。因为A3和A2的数据有些不同,这里只是简单的在22个数据后填充4个0传到预测模块。

BloodTestReportOCR/view.py

@app.route("/predict_pd",methods=['POST'])def predict_pd():   print ("predict now!")   data = json.loads(request.form.get('data'))   ss = data['value']   arr = [[[]]]   for i in ss:       arr[0][0].append(float(i))   for i in range(4):       arr[0][0].append(0)   swig_paddle.initPaddle("--use_gpu=0")   sex = prediction_sex.predict(arr)   age = prediction_age.predict(arr)   result = {       "sex":sex,       "age":int(age)    }return json.dumps(result)

PaddlePaddle/prediction_age.py

def predict(data):   path=os.path.split(os.path.realpath(__file__))[0]   conf = parse_config(path+"/trainer_config_age.py","is_predict=1")   print conf.data_config.load_data_args   network =swig_paddle.GradientMachine.createFromConfigProto(conf.model_config)   network.loadParameters(path+"/output_age/pass-00099")   converter = DataProviderConverter([dense_vector(26)])   inArg = converter(data)   network.forwardTest(inArg)   output = network.getLayerOutputs("__fc_layer_0__")   prob = output["__fc_layer_0__"].mean(0)   lab = np.argsort(-prob)   return lab[0]if __name__ == '__main__':   swig_paddle.initPaddle("--use_gpu=0")   csvfile = file('predict.csv', 'rb')   reader = csv.reader(csvfile)   rows= [row for row in reader]   row=rows[1]   print '实际年龄:'+row[2]   del row[0]   del row[0]    del row[0]   data = [[[]]]   for j in row:       data[0][0].append(float(j))   csvfile.close()print '预测年龄:'+str(predict(data))

PaddlePaddle/prediction_sex.py

def predict(data):   path=os.path.split(os.path.realpath(__file__))[0]   conf = parse_config(path+"/trainer_config_sex.py","is_predict=1")   print conf.data_config.load_data_args   network =swig_paddle.GradientMachine.createFromConfigProto(conf.model_config)   network.loadParameters(path+"/output_sex/pass-00029")   converter = DataProviderConverter([dense_vector(26)])   inArg = converter(data)   network.forwardTest(inArg)   output = network.getLayerOutputs("__fc_layer_0__")   prob = output["__fc_layer_0__"].mean(0)   lab = np.argsort(-prob)   return lab[0]if __name__ == '__main__':   swig_paddle.initPaddle("--use_gpu=0")   csvfile = file('predict.csv', 'rb')   reader = csv.reader(csvfile)   rows= [row for row in reader]    #预测第一行   row=rows[1]   sex='女'   if(row[1]=='\xc4\xd0'):       sex='男'   print '实际性别:'+sex   del row[0]   del row[0]   del row[0]   data = [[[]]]   for j in row:       data[0][0].append(float(j))   csvfile.close()   if(predict(data)==1):       print'预测性别:男'   else:       print'预测性别:女'

BloodTestReportOCR/static/index.html

<button type="button" v-on:click="predict_pd()" class="btn btn-primary btn-lg btn-block">predict_pd</button>predict_pd: function(event) {                data = [];                for(var i=0;i<13;i++)                    data[i] = Number(this.report_items_left[i].value);                for(var i=0;i<9;i++)                    data[13+i] = Number(this.report_items_right[i].value);                var data = {                    data: JSON.stringify(({                        "value":data                    }))                };                $.ajax({                    url: "/predict_pd",                    type: 'POST',                    data: data,                    success: function(data) {                        var obj = JSON.parse(data)                        if(obj.sex == 1)                            var sexsex = "男";                        else                            var sexsex = "女"                        alert("性别:" + sexsex + "\n年龄:" + obj.age);                    }                })            }

总结

上了这门课,我才知道pr是怎么回事,虽然也选过孟老师的高软,但由于不懂web开发,对微信app也没什么兴趣,所以完全是克隆大神的代码,自己跑一遍而已。记得第一次实验后,老师说好像有问题,我就修复了服务器端只监听localhost的不能称为bug的bug,然后我的第一次pr就被接受了,这使我信心大增,才有了后面的pr,虽然也有拒绝的,但我学会了一项程序员必备的技能。神经网络这东西听着高大上,但在深度学习平台的帮助下,搭建一个神经网络如同搭积木一样简单。其他同学在课堂上的分享虽然只听懂大概,但好歹也算对机器学习入了门,以后如果要继续研究也有了基础。总之很幸运选了这门课,其他同学pr的灰度化二值化什么的我都整合到自己的工程实践项目里了。一个遗憾就是没做过分享,我是一个比较内向的人,如果不是强制的,我一般不会主动上台演讲,这方面的能力还是以后慢慢培养吧。



1 0
原创粉丝点击