fall-2016-网络程序设计心得体会

来源:互联网 发布:二维码标签制作软件 编辑:程序博客网 时间:2024/04/30 09:53

项目介绍:

本课程的目标是通过分析用户上传的血常规图片来预测出用户的性别和年龄。

项目演示:


版本库URL:https://coding.net/u/wjiafengw/p/np2016-1765748544/git


下图是基本页面:



1:上传图片并点击提交

注意:图片必须为jpg/jgeg/png格式并且化验单应尽量平整




2:点击生成报告

注意:报告表格里的数字为ocr对化验单的识别,识别结果可能有错,需要手动校正




3:点击“predict”




运行和环境搭建:


安装numpy$ sudo apt-get install Python-numpy 安装OpenCV$ sudo apt-get install python-opencv 安装pytesseract$ sudo apt-get install tesseract-ocr$ sudo pip install pytesseract$ sudo apt-get install python-tk$ sudo pip install pillow 安装Flask框架$ sudo pip install Flask 安装mongodb$ sudo apt-get install mongodb # 如果提示no modulename mongodb, 先执行sudo apt-get update$ sudo service mongodb started$ sudo pip install pymongo 安装Tensorflow$ sudo apt-get install python-numpy$ sudo apt-get install python-imaging$ pip install --upgradehttps://storage.googleapis.com/tensorflow/Linux/cpu/tensorflow-0.12.0rc0-cp27-none-linux_x86_64.whl运行$ cd BloodTestReportOCR$ python view.py # upload图像,在浏览器打开http://yourip:8080

个人对项目的理解:


我认为这个项目有三个难点:1)项目整体框架的搭建 2)图片的处理和ocr识别 3)利用机器学习算法进行预测


Pull && Request:





第一个pull是用RNN模型对性别进行预测,正确率0.7左右(merge)

第二个pull是将RNN集成到A2中,性别准确率0.7,年龄0.3(将年龄划分成10个区间)

并且修改了config.py配置文件,使得可以自由选择模型(未处理)


图像处理部分:

由于之前没有接触过图像处理,自己也对这部分没有代码贡献。通过学习,还是能大概看懂这部分的流程:

从前端接收图片(view.upload),为了进行ocr识别(ImageFilter.ocr),他会先经过一个过滤器(ImageFilter.filter)过滤掉不合格的图片,然后进行透视变换(ImageFilter.perspect),这也是图片处理的核心。其原理是根据某个阈值用长方形ROI去提取表格中的三条黑线,然后根据三条线对倾斜的报告单照片执行了变换,并将表格区域转化成一张1000*760的图保存。之后,对该图片进行剪切(ImageFilter.autocut),保存在temp_pics。为了提高识别的准确率,会有一些灰度化、二值化、膨胀等方法(Imgproc.digiting)对裁剪过的小图进行处理,然后调用外部API进行识别(pytesseract.image_to_string),并将其结果封装成json返回。最后,将图片信息和json保存到数据库。


机器学习部分:



目前深度学习框架有很多,tensorflow、caffe、paddlepaddle等等,各有优势和特色,本人选择的是tensorflow。线上的tensorflow代码采用的是双隐层的多层感知机的模型,由于之前了解过RNN相关的知识,自然想到了在tensorflow下用RNN作为模型来预测性别和年龄并且将它集成到A2。RNN大家都有所了解,特别适合用来做自然语言的处理,但并不意味着它不能用来预测其他东西。在这个项目中,使用RNN这个模型效果尚可。我们甚至不用进行去均值、归一化等方法就能达到性别70%以上的准确率。然而预测年龄的准确率还是比较低,我采用的是将年龄划分成10个区间,最后的准确率也只能接近30%。由于我在训练、预测的时候性别和年龄是封装在不同函数里,而这两部分代码高度相似,所以以下只贴年龄部分的代码:


训练RNN模型并保存模型:

# Parameterslearning_rate = 0.001training_iters = 200display_step = 10# Network Parametersn_input = 11 #每个时间步骤传入11个特征n_steps = 2 #分为2个时间步骤n_hidden = 128 #隐藏层神经元的个数n_classes = 10 # 将年龄分成10类#定义年龄的one_hotdef one_hot(a, length):    b = np.zeros([length, 10])    for i in range(length):        tmp = a[i] / 10        b[i][int(tmp)] = 1    return b#读数据集,共2058行,24列(第一列为性别,第二列为年龄)data = np.loadtxt(open("./data.csv","rb"),delimiter=",",skiprows=0)#我们取前1858行作为我们的训练集train_data = data[0:1858, :]#剩余的作为测试集test_data = data[1858:, :]#第二列是年龄train_label_age = train_data[:, 1:2]#转one_hottrain_label_age = one_hot(train_label_age,train_data.shape[0])train_data = train_data[:, 2:]#转成要求的格式train_data = np.reshape(train_data, (1858,n_steps,n_input))#下面对测试集的处理同上test_label_age = test_data[:, 1:2]test_label_age = one_hot(test_label_age,test_data.shape[0])test_data = test_data[:, 2:]test_data = np.reshape(test_data, (200,n_steps,n_input))# tf Graph inputx = tf.placeholder("float", [None, n_steps, n_input])y = tf.placeholder("float", [None, n_classes])# Define weightsweights = {    'out': tf.Variable(tf.random_normal([n_hidden, n_classes]))}biases = {    'out': tf.Variable(tf.random_normal([n_classes]))}def RNN(x, weights, biases):    #下面这三行的代码主要是把我们传进来的数据(batch_size,n_steps,n_input)这种形状的数据    #分为n_steps个时间步骤,每个时间步骤数据的形状是(batch_size,n_input)    #矩阵的转置    #将(batch_size, n_steps, n_input)变为(n_steps, batch_size, n_input)    #此例中shape从(1858,2,11)变为(2,1858,11)    x = tf.transpose(x, [1, 0, 2])    #降维    #将(n_steps, batch_size, n_input)变为 (n_steps*batch_size, n_input)    #此例中shape从(2,1858,11)变为(2*1858,11)    x = tf.reshape(x, [-1, n_input])        #拆分    #此例拆分为:split0:shape:(1858,11)和split1:shape:(1858,11)    #经过这一系列操作将数据拆分成两个时间步骤,每个时间步骤传入的是一个1858行11列的矩阵    x = tf.split(0, n_steps, x)    # Define a lstm cell with tensorflow    lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)    # Get lstm cell output    outputs, states = rnn.rnn(lstm_cell, x, dtype=tf.float32)# output[-1]为上个时间的记忆,形状为(1858,128)# weights[‘out’]形状为(128,10)# return的形状为(1858,10)    return tf.matmul(outputs[-1], weights['out']) + biases['out']pred = RNN(x, weights, biases)# Define loss and optimizercost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred, y))optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)# Evaluate modelcorrect_pred = tf.equal(tf.argmax(pred,1), tf.argmax(y,1))accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))# Initializing the variablesinit = tf.global_variables_initializer()#为了保存模型saver=tf.train.Saver()# Launch the graphwith tf.Session() as sess:    sess.run(init)    step = 1    # Keep training until reach max iterationswhile step < training_iters:        sess.run(optimizer, feed_dict={x: train_data, y: train_label_age})        if step % display_step == 0:            # Calculate batch accuracy            acc = sess.run(accuracy, feed_dict={x: train_data, y: train_label_age})            # Calculate batch loss            loss = sess.run(cost, feed_dict={x: train_data, y: train_label_age})            #每迭代10次打印出当前的准确率和损失            print("Iter " + str(step) + ", Loss= " + \                  "{:.6f}".format(loss) + ", Training Accuracy= " + \                  "{:.5f}".format(acc))        step += 1print("Optimization Finished!")#保存我们的训练模型    save_path = saver.save(sess, "./rnn_model/rnn_age_model/model.ckpt")    #print("model save in file:%s" %save_path)    #打印出测试集的准确率    print("Testing Accuracy:", \sess.run(accuracy, feed_dict={x: test_data, y: test_label_age}))

下面是运行的结果:





预测部分:

会先从config.py中读取MODEL参数,决定使用NN或者RNN模型(0代表RNN模型,1代表ANN)

view.py
def predict():    print ("predict now!")    data = json.loads(request.form.get('data'))    ss = data['value']    arr = numpy.array(ss)    arr = numpy.reshape(arr, [1, 22])    if app.config['MODEL'] == 0:        sex = rnn_predict.predict_sex(arr)        age = rnn_predict.predict_age(arr)        result = {            "sex": sex,            "age": age        }    elif app.config['MODEL'] == 1:        sex, age = tf_predict.predict(arr)        result = {            "sex": sex,            "age": int(age)        }return json.dumps(result)

rnn_predict.py
def predict_age(data_predict):    tf.reset_default_graph()    # Network Parametersn_input = 11  n_steps = 2  n_hidden = 128  n_classes = 10     data_predict = np.reshape(data_predict, (1,n_steps, n_input))    # tf Graph input    x = tf.placeholder("float", [None, n_steps, n_input])    y = tf.placeholder("float", [None, n_classes])    # Define weights    weights = {        'out': tf.Variable(tf.random_normal([n_hidden, n_classes]))    }    biases = {        'out': tf.Variable(tf.random_normal([n_classes]))    }    def RNN(x, weights, biases):        x = tf.transpose(x, [1, 0, 2])        x = tf.reshape(x, [-1, n_input])        x = tf.split(0, n_steps, x)        # Define a lstm cell with tensorflow        lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)        # Get lstm cell output        outputs, states = rnn.rnn(lstm_cell, x, dtype=tf.float32)        # Linear activation, using rnn inner loop last output        return tf.matmul(outputs[-1], weights['out']) + biases['out']    pred = RNN(x, weights, biases)    # Initializing the variables    init = tf.global_variables_initializer()        saver = tf.train.Saver()    # Launch the graph    with tf.Session() as sess:        sess.run(init)        #读之前保存的模型        saver.restore(sess,"./rnn_model/rnn_age_model/model.ckpt")        #预测        p = sess.run(pred, feed_dict={x:data_predict})# print(tf.argmax(p, 1))# 找出最大的得分向量    max = p[0][0]    max_i = 0    for i in range(n_classes):        if p[0][i] > max:            max_i = i            max = p[0][i]    age_result = str(max_i * 10) + "~" + str((max_i+1) *10 -1)return age_result

总结:


说实话当初听到学长说这门课挂科率高有点想退课的冲动,然而最终还是没有选择放弃,现在看来收获也不小。没有学过python,没有接触过图像处理,更没有机器学习的编程经验。在很长的一段时间内都感到无从下手。同学推荐了本周志华的《机器学习》,从头开始看起。发现一些听起来逼格很高的词(比如说“卷积”和“池话”)原理也不是太难,这算是收获之一吧?另一个收获就是在学习新的模型的时候,可能未必需要对模型内部的一些数学原理搞得太懂(其实是想搞懂也搞不懂!)只需要知道大概的流程、模型适用的场合、以及怎么把别人的数据集换成我们的数据集就行了。











0 0
原创粉丝点击