基于深度学习神经网络等机器学习技术实现一个医学辅助诊断的专家系统原型

2023-05-16

3.运行环境搭建   
操作系统:Ubantu
(1)安装python模块
sudo apt-get install python-pip
(2)安装numpy
sudo apt-get install python-numpy
(3)安装opencv
sudo apt-get install python-opencv
(4)安装OCR和预处理相关依赖
sudo apt-get install tesseract-ocr
sudo pip install pytesseract
sudo apt-get install pyton-tk
sudo pip install pillow
(5)安装Flask框架、mongo
sudo pip install Flask
sudo apt-get install mongodb
sudo service mongodb started
sudo pip install pymongo
4.Demo 
  (1)定位到BloodTestReportOCR文件夹,输入python view.py 
  网络程序设计学习总结

  (2)打开浏览器,输入localhost:8080     
  网络程序设计学习总结

  (3)选择样本图片上传后得到矫正后的图片
  网络程序设计学习总结

  (4)点击“生成报告”,得到OCR的结果
  网络程序设计学习总结

  (5)点击“predict”,得到预测结果 
  网络程序设计学习总结

 
  • 代码分析
 
 
1.相关文件介绍 
view.py 
Web端上传图片到服务器,存入mongodb并获取oid,稍作修整,希望能往REST架构设计,目前还不完善
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则可以屏蔽,但是会导致其他图片识别困难。
就现在来看,得到较好结果的前提主要有三个

(1)化验单尽量平整

(2)图片中应该包含全部的三条黑线

(3)图片尽量不要包含化验单的边缘,如果有的话,请尽量避开有阴影的边缘。

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

 
2.Code Review 
(1)Web模块
Vue.js
在本项目中,利用Vue.js对数据进行绑定,以表格的左半部分为例
for (var i = 0; i < json_data["bloodtest"].length; i++) {
    if(i<<span style="BOX-SIZING: border-box; COLOR: rgb(0,102,102)" class="hljs-number">13){
        report.report_items_left.push({
            count: i+1,
            name: json_data.bloodtest[i]["name"],
            alias: json_data.bloodtest[i].alias,
            value: json_data.bloodtest[i].value,
            range: json_data.bloodtest[i].range,
            unit: json_data.bloodtest[i].unit
        });
    }
} 
 然后当用户在界面修改后,因为已经绑定,只需要直接调用data,即可获取到相关值
 
data[i] = Number(this.report_items_left[i].value);
Flask 
首先在运行时启动服务器
 
app = Flask(__name__, static_url_path="")
app.config.from_object('config')
app.run(host=app.config['SERVER_HOST'], port=app.config['SERVER_PORT'])
然后在前端利用Ajax就可以访问到后端的对应函数
 
url = 'report/' + url.split('/')[2];
$.ajax({
    url: url,
    success: function(data) {
        //对返回的data进行处理
在后端接受前端的http访问请求
 
@app.route('/report/')
def get_report(fid):
    try:
        file = db.files.find_one(bson.objectid.ObjectId(fid))
MongoDB
在本课程中,用到的数据库是MongoDB,主要用于将矫正后的图片与OCR识别结果存入数据库中。
首先是打开服务的时候连接数据库
 
db = MongoClient(app.config['DB_HOST'], app.config['DB_PORT']).test
在上传图片后,将矫正后的图片以及识别到的各项数值存入数据库中
 
c = dict(report_data=report_data, content=bson.binary.Binary(content.getvalue()), filename=secure_filename(f.name),mime=mime)
db.files.save(c)
也可利用fid,进行结果查询
 
try:
    file = db.files.find_one(bson.objectid.ObjectId(fid))
    if file is None:
        raise bson.errors.InvalidId()
    print 'type before transform:\n', type(file['report_data'])
    report_data = bson.json_util.dumps(file['report_data'])
 
(2)图像OCR模块
 先将我们所采用的报告单的图片格式作为识别标准,通过对图片的预处理,包括灰度化、模糊、开闭运算等等,然后重点根据图片的特征,即图中的三条基准线,对图片进行水平方向上的梯度检测,然后根据检测出的线的位置,逐步确定表头表尾,最终对图片进行裁剪。
 
预处理
 在获取到上传的血常规化验单图片后,项目对其进行了预处理,作用主要是为了减小噪声,为后边的识别算法服务,在这里主要用到了以下两个方法:
a)高斯平滑
 
img_gb = cv2.GaussianBlur(img_gray, (gb_param, gb_param), 0)

       b)腐蚀、膨胀

closed = cv2.morphologyEx(img_gb, cv2.MORPH_CLOSE, kernel)
opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel)
 
线段检测
 为了对图片各个数值所在区域进行定位,这里需要检测出图片中比较明显的标识,3条黑线,然后利用这三条线对整张图片进行标定。主要用到了以下3个步骤:
a)采用Canny算子提取边
 
edges = cv2.Canny(opened, canny_param_lower , canny_param_upper)
b)调用CV2模块的findContours提取矩形轮廓,筛选对角线大于阀值的轮廓
 
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

       c)求最小外接矩形

def getbox(i):
            rect = cv2.minAreaRect(contours[i])
            box = cv2.cv.BoxPoints(rect)
            box = np.int0(box)
            return box
 

将轮廓变成线:比较最小外接矩形相邻两条边的长短,以两条短边的中点作为线的两端;

若线数量大于三则根据线长短继续筛选长线。根据三条线间的距离确定表格头部和内容的位置;

利用向量叉乘不可变性确定起始点(若方向相反,结果为负),将表格内容往上包含头部的一些年龄性别信息。

 OCR
这里主要利用OCR对血常规报告中的字符进行识别,得到具体的数值,用于后续的预测。其中步骤主要是根据上边求得的三条线段对图片进行透射变换,根据标定好的像素位置,利用pytesseract进行字符识别。

     a)透射变换

#设定透视变换的矩阵
points = np.array([[line_upper[0][0], line_upper[0][1]], [line_upper[1][0], line_upper[1][1]], [line_lower[0][0], line_lower[0][1]], [line_lower[1][0], line_lower[1][1]]],np.float32)
standard = np.array([[0,0], [1000, 0], [0, 760], [1000, 760]],np.float32)

#使用透视变换将表格区域转换为一个1000*760的图
PerspectiveMatrix = cv2.getPerspectiveTransform(points,standard)
self.PerspectiveImg = cv2.warpPerspective(self.img, PerspectiveMatrix, (1000, 760))
 

     b)截图

def autocut(self, num, param=default):
   if self.PerspectiveImg is None:
        self.PerspectivImg = self.filter(param)
        # 仍然是空,说明不是报告
        if self.PerspectiveImg is None:
            return -1

        #输出年龄
        img_age = self.PerspectiveImg[15 : 70, 585 : 690]
        cv2.imwrite(self.output_path + 'age.jpg', img_age)

        #输出性别
        img_gender = self.PerspectiveImg[15 : 58, 365 : 420]
        cv2.imwrite(self.output_path + 'gender.jpg', img_gender)

        #输出时间
        img_time = self.PerspectiveImg[722 : 760, 430 : 630]
        cv2.imwrite(self.output_path + 'time.jpg', img_time)

        #转换后的图分辨率是已知的,所以直接从这个点开始读数据就可以了
        startpoint = [199, 132]
        vertical_lenth = 37
        lateral_lenth = 80

  def getobjname(i, x, y):
       region_roi = self.PerspectiveImg[y : y+vertical_lenth, x : x+170]
       filename = self.output_path + 'p' + str(i) + '.jpg'
       cv2.imwrite(filename, region_roi)

  def getobjdata(i, x, y):
       region_roi = self.PerspectiveImg[y : y+vertical_lenth, x : x+lateral_lenth]
       filename = self.output_path + 'data' + str(i) + '.jpg'
       cv2.imwrite(filename, region_roi)

       #输出图片
  if num <= 13 and num > 0:
       for i in range(num):
          getobjname(int(i), 25, startpoint[1])
          getobjdata(int(i), startpoint[0], startpoint[1])
          startpoint[1] = startpoint[1] + 40
  elif num > 13:
       for i in range(13):
          getobjname(int(i), 25, startpoint[1])
          getobjdata(int(i), startpoint[0], startpoint[1])
          startpoint[1] = startpoint[1] + 40
          startpoint = [700, 135]
       for i in range(num-13):
          getobjname(int(i+13), 535, startpoint[1])
          getobjdata(int(i+13), startpoint[0], startpoint[1])
          startpoint[1] = startpoint[1] + 40


        #正常结束返回0
        return 0

      c)对每份数据调用pytesserac的OCR库进行识别


  

  
'''
ocr函数用于对img进行ocr识别,他会先进行剪切,之后进一步做ocr识别,返回一个json对象
如果剪切失败,则返回None
@num 规定剪切项目数
'''
def ocr(self, num):
digtitsresult = []
chiresult = []
# 不是报告
if self.autocut(num) ==  -1:
return  None
# 识别
def image_to_string(image, flag=True):
if flag:
text = pytesseract.image_to_string(Image.fromarray(image), config= '-psm 7 digits')
else:
text = pytesseract.image_to_string(Image.fromarray(image), lang= 'chi_sim', config= ' -psm 7 Bloodtest')
return text
# 读取图片
def read(url):
image = cv2.imread(url)
return image
# load json example
with open( 'bloodtestdata.json'as json_file:
data = json.load(json_file)
# 识别检测项目编号及数字
for i  in range(num):
item = read( 'temp_pics/p' + str(i) +  '.jpg')
item_num = classifier.getItemNum(item)
image = read( 'temp_pics/data' + str(i) +  '.jpg')
image = imgproc.digitsimg(image)
digtitstr = image_to_string(image)
digtitstr = digtitstr.replace( " "'')
digtitstr = digtitstr.replace( "-"'')
digtitstr = digtitstr.strip( ".")
data[ 'bloodtest'][item_num][ 'value'] = digtitstr
json_data = json.dumps(data,ensure_ascii= False,indent= 4)
return json_data
 
    (3)预测模块
 
     数值预处理 
      为了提高机器学习的准确程度,避免由于数据本身的数值不统一等对学习结果造成影响,需要对样本集进行一定的预处理。在本门课程中,我用到的预处理方法主要是去均值与归一化。 
 
 a)去均值
去均值的具体做法是在每个样本上减去数据的统计平均值,去均值的意义主要在于扩大分类的 效果。查看tenserflow的MNIST源码时可以看到,程序中对每个像素点的像素值都减去了128,这 就是去均值。 
 
  b)归一化
数据尺度归一化的原因是:数据中每个维度表示的意义不同,所以有可能导致该维度的变化范

围不同,因此有必要将他们都归一化到一个固定的范围,一般情况下是归一化到[0 1]或者[-1 1]。同样在TensorFlow的MNIST源码中可以看到,去均值后,会将每点的像素值除以128,进行了归一化操作。 
      下边是本门课程中写的去均值与归一化代码,a是训练集,b是需要预测的一组样本。返回结果是去均值与归一化之后的样本b。

def normalized(a,b):
    for i in range(22):
        tmp = np.mean(a[:, i])
        a[:, i] = a[:, i] - tmp
        b[:, i] = b[:, i] - tmp
        if np.min(a[:, i]) != np.max(a[:, i]):
            b[:, i] = 2 * (b[:, i] - np.min(a[:, i])) / (np.max(a[:, i]) - np.min(a[:, i])) - 1
        else:
            b[:, i] = 0
    return b
    tensorflow初始化并预测
 
def predict(data_predict):
    tf.reset_default_graph()
    data_nor = np.loadtxt(open("./data.csv", "rb"), delimiter=",", skiprows=0)

    data_predict = normalized(data_nor[:, 2:], data_predict)

    '''
        参数
        '''
    learning_rate = 0.005
    display_step = 100
    n_input = 22

    n_hidden_1_age = 32
    n_hidden_2_age = 16
    n_classes_age = 1

    n_hidden_1_sex = 16
    n_hidden_2_sex = 8
    n_classes_sex = 2
    data = np.loadtxt(open("./data.csv", "rb"), delimiter=",", skiprows=0)
    '''
    建立年龄模型
    '''
    x_age = tf.placeholder("float", [None, n_input])
    y_age = tf.placeholder("float", [None, n_classes_age])

    def multilayer_perceptron_age(x_age, weights_age, biases_age):
        # Hidden layer with RELU activation
        layer_1 = tf.add(tf.matmul(x_age, weights_age['h1']), biases_age['b1'])
        layer_1 = tf.nn.relu(layer_1)
        # Hidden layer with RELU activation
        layer_2 = tf.add(tf.matmul(layer_1, weights_age['h2']), biases_age['b2'])
        layer_2 = tf.nn.relu(layer_2)
        # Output layer with linear activation
        out_layer = tf.matmul(layer_2, weights_age['out']) + biases_age['out']
        return out_layer

    weights_age = {
        'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1_age])),
        'h2': tf.Variable(tf.random_normal([n_hidden_1_age, n_hidden_2_age])),
        'out': tf.Variable(tf.random_normal([n_hidden_2_age, n_classes_age]))
    }
    biases_age = {
        'b1': tf.Variable(tf.random_normal([n_hidden_1_age])),
        'b2': tf.Variable(tf.random_normal([n_hidden_2_age])),
        'out': tf.Variable(tf.random_normal([n_classes_age]))
    }
    pred_age = multilayer_perceptron_age(x_age, weights_age, biases_age)
    '''
    建立性别模型
    '''
    x_sex = tf.placeholder("float", [None, n_input])
    y_sex = tf.placeholder("float", [None, n_classes_sex])

    def multilayer_perceptron_sex(x_sex, weights_sex, biases_sex):
        # Hidden layer with RELU activation
        layer_1 = tf.add(tf.matmul(x_sex, weights_sex['h1']), biases_sex['b1'])
        layer_1 = tf.nn.relu(layer_1)
        # Hidden layer with RELU activation
        layer_2 = tf.add(tf.matmul(layer_1, weights_sex['h2']), biases_sex['b2'])
        layer_2 = tf.nn.relu(layer_2)
        # Output layer with linear activation
        out_layer = tf.matmul(layer_2, weights_sex['out']) + biases_sex['out']
        return out_layer

    weights_sex = {
        'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1_sex])),
        'h2': tf.Variable(tf.random_normal([n_hidden_1_sex, n_hidden_2_sex])),
        'out': tf.Variable(tf.random_normal([n_hidden_2_sex, n_classes_sex]))
    }
    biases_sex = {
        'b1': tf.Variable(tf.random_normal([n_hidden_1_sex])),
        'b2': tf.Variable(tf.random_normal([n_hidden_2_sex])),
        'out': tf.Variable(tf.random_normal([n_classes_sex]))
    }
    pred_sex = multilayer_perceptron_sex(x_sex, weights_sex, biases_sex)

    '''
    共同的初始化
    '''
    saver = tf.train.Saver()
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        saver.restore(sess, "./model.ckpt")
        print ("load model success!")
        p_sex = sess.run(pred_sex, feed_dict={x_sex: data_predict})
        p_age = sess.run(pred_age, feed_dict={x_age: data_predict})
    if p_sex[0][0] > p_sex[0][1]:
        sex_result = 1
    else:
        sex_result = 0

    age_result = p_age[0][0] * 50 +50

    return sex_result,age_result

A1:神经网络实现手写识别系统

这个项目可以说是深度学习的hello world。可以通过这个项目来入门机器学习。但是在跑的过程中还是遇到了一些麻烦。因为原来我的电脑中装的是python3.5,和pyhton2.7中的有些包是不兼容的。所以后来又重新装了pyhton2.7总算跑起来了。

当然跑不是最重要的,重要的是理解算法。这是一个最简单的神经网络,只有一层输入层,一层隐藏层,一个输出层。输入是20乘20,也就是400个像素点,400行一列的矩阵。着色的部分为1,否则为0。输出是一个10行一列的one-hot矩阵代表是哪个数字。采用反向传播算法,它通过计算误差率然后系统根据误差改变网络的权值矩阵和偏置向量来进行训练。

初次之外,我还对一个完整的项目的运作有了了解。数据怎样从前端流向后端,再调用算法进行计算,最后显示在网页上。

  用户接口(ocr.html)--html网页

  客户端(ocr.js)--处理在客户端接收到的响应、传递服务器的响应

  服务器(server.py)--由Python标准库BaseHTTPServer实现,接收从客户端发来的训练或是预测请求,使用POST报文

  神经网络(ocr.py) --实现具体算法

  神经网络设计脚本(neural_network_design.py)--测试用


2 调用CV2模块的findContours提取矩形轮廓,筛选对角线大于阈值的轮廓

contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

def getbox(i):
rect = cv2.minAreaRect(contours[i])
box = cv2.cv.BoxPoints(rect)
box = np.int0(box)
return box

def distance(box):
delta1 = box[0]-box[2]
delta2 = box[1]-box[3]
distance1 = np.dot(delta1,delta1)
distance2 = np.dot(delta2,delta2)
distance_avg = (distance1 + distance2) / 2
return distance_avg

# 筛选出对角线足够大的几个轮廓
found = []
for i in range(len(contours)):
box = getbox(i)
distance_arr = distance(box)
if distance_arr > ref_lenth:
found.append([i, box])

def getline(box):
if np.dot(box[1]-box[2],box[1]-box[2]) < np.dot(box[0]-box[1],box[0]-box[1]):
point1 = (box[1] + box[2]) / 2
point2 = (box[3] + box[0]) / 2
lenth = np.dot(point1-point2, point1-point2)
return point1, point2, lenth
else:
point1 = (box[0] + box[1]) / 2
point2 = (box[2] + box[3]) / 2
lenth = np.dot(point1-point2, point1-point2)
return point1, point2, lenth

def cmp(p1, p2):
delta = p1 - p2
distance = np.dot(delta, delta)
if distance < img_sp[0] * img_sp[1] * ref_close_multiplier:
return 1
else:
return 0

def linecmp(l1, l2):
f_point1 = l1[0]
f_point2 = l1[1]
f_lenth = l1[2]
b_point1 = l2[0]
b_point2 = l2[1]
b_lenth = l2[2]
if cmp(f_point1,b_point1) or cmp(f_point1,b_point2) or cmp(f_point2,b_point1) or cmp(f_point2,b_point2):
if f_lenth > b_lenth:
return 1
else:
return -1
else:
return 0

def deleteline(line, j):
lenth = len(line)
for i in range(lenth):
if line[i] is j:
del line[i]
return

筛选对角线大于阈值的矩形
4 使用透视变换将表格区域转换为一个1000*760的图,得到可用于ocr剪切的照片 
autocut(self, num, param=default)函数用于剪切ImageFilter中的img成员,剪切之前调用filter(param)判断是否为可识别的图像,剪切之后临时图片保存在out_path,如果剪切失败,返回-1,成功返回0 
ocr(self, num)函数用于对img进行ocr识别,返回一个json格式数据。 
ocr流程图

A3:根据血常规检验的各项数据预测年龄和性别

下面我们要做的就是构建机器学习模型了。我们使用了2000多份血常规报告,90%用于训练,10%用于检验。我使用的是基于tensorflow实现的神经网络

神经网络原理

神经网络由能够互相通信的节点构成,赫布理论解释了人体的神经网络是如何通过改变自身的结构和神经连接的强度来记忆某种模式的。而人工智能中的神经网络与此类似。请看下图,最左一列蓝色节点是输入节点,最右列节点是输出节点,中间节点是隐藏节点。该图结构是分层的,隐藏的部分有时候也会分为多个隐藏层。如果使用的层数非常多就会变成我们平常说的深度学习了。 
一个简单的神经网络
神经网络属于监督学习,那么多半就三件事,决定模型参数,通过数据集训练学习,训练好后就能到分类工具/识别系统用了。数据集可以分为2部分(训练集,验证集),也可以分为3部分(训练集,验证集,测试集),训练集可以看作平时做的习题集(可反复做)。通过不断的训练减少损失,我们就可以得到最优的参数,即偏置向量和权重。

调参经验

在总结点数量差不多的情况下,深层但每层的隐藏节点数较少的网络较之浅层但每层节点数的网络效果要好。其它参数,近两年论文基本都用同样的参数设定:迭代几十到几百epoch。sgd,mini batch size从几十到几百皆可。步长0.1,可手动收缩,weight decay取0.005,momentum取0.9。dropout加relu。weight用高斯分布初始化,bias全初始化为0。输入特征和预测目标都做好归一化也有助于提高准确率。 
在A2中,因为我写的神经网络和版本库上的类似,所以就没有上传,下面讲讲我的贡献,数据封装和可视化

数据封装

因为看到minist手写识别的代码中把数据集封装成了对象,用起来很方便,所以就做了这个。

train = Traindata()                  #初始化
gender = train.gender                #性别的one-hot矩阵
age = train.age                      #年龄
para = train.parameter               #26项指标矩阵
train.next_batch_gender(n)           #随机抽取n项数据对应的指标及其性别
train.next_batch_age(n)              #同上

TensorBoard:可视化学习

官方文档中的介绍是这样的:

TensorBoard 涉及到的运算,通常是在训练庞大的深度神经网络中出现的复杂而又难以理解的运算。 
为了更方便 TensorFlow 程序的理解、调试与优化,我们发布了一套叫做 TensorBoard 的可视化工具。你可以用 TensorBoard 来展现你的 TensorFlow 图像,绘制图像生成的定量指标图以及附加数据。

想要可视化,首先要定义图层和对节点命名: 
使用with tf.name_scope('inputs')xsys包含进来,形成一个大的图层,图层的名字就是with tf.name_scope()方法里的参数。

with tf.name_scope('inputs'): 
# define placeholder for inputs to network 
xs = tf.placeholder(tf.float32, [None, 1]) 
ys = tf.placeholder(tf.float32, [None, 1])

然后再次对ys指定名称y_inxs同理:

ys= tf.placeholder(tf.loat32, [None, 1],name='y_in')

在定义完大的框架layer之后,也可以定义每一个’框架‘里面的小部件:(Weights biases 和 activation function)。如对 Weights 定义: 定义的方法同上,可以使用tf.name.scope()方法,同时也可以在Weights中指定名称W。 即为:

def add_layer(inputs, in_size, out_size, activation_function=None): 
#define layer name 
with tf.name_scope('layer'): 
#define weights name 
    with tf.name_scope('weights'): 
    Weights= tf.Variable(tf.random_normal([in_size, out_size]),name='W') 
#and so on......

接下来,我们为层中的Weights设置变化图, tensorflow中提供了tf.histogram_summary()方法,用来绘制图片, 第一个参数是图表的名称, 第二个参数是图表要记录的变量

tf.histogram_summary(layer_name+'/weights',Weights)

Loss 的变化图和之前设置的方法略有不同. loss是在tesnorBorad 的event下面的, 这是由于我们使用的是tf.scalar_summary() 方法

with tf.name_scope('loss'): 
    loss= tf.reduce_mean(tf.reduce_sum( tf.square(ys- prediction), reduction_indices=[1])) 
    tf.scalar_summary('loss',loss)

接下来, 开始合并打包,tf.merge_all_summaries() 方法会对我们所有的 summaries合并到一起. 因此在原有代码片段中添加:

sess= tf.Session()
merged= tf.merge_all_summaries()
# tf.train.SummaryWriter soon be deprecated, use following
writer = tf.summary.FileWriter("logs/", sess.graph)
sess.run(tf.initialize_all_variables())

程序运行完毕之后, 会产生logs目录 , 使用命令 tesnsorboard --logdir='logs/',打开终端中输出的URL地址即可。

运行

代码

以年龄预测为例:

# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np
import csv
import math

label_orign2 = []
data_orign2 = []
sex_orign2 = []
age_orign2 = []

#读预测数据
with open('predict.csv','rb') as precsv2:
reader2 = csv.reader(precsv2)
for line2 in reader2:

if reader2.line_num == 1:
continue 
label_origntemp2 = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] #升维度
label_origntemp2.insert(int(math.floor(float(line2[2])/10)),float(math.floor(float(line2[2])/10)))
label_orign2.append(label_origntemp2)
data_orign2.append(line2[3:])
label_np_arr2 = np.array(label_orign2)
data_np_arr2 = np.array(data_orign2)
sex_np_arr2 = np.array(sex_orign2)

data_len2 = data_np_arr2.shape[1]
data_num2 = data_np_arr2.shape[0]

label_orign = []
data_orign = []
sex_orign = []
age_orign = []
#读训练数据
with open('train.csv','rb') as precsv:
reader = csv.reader(precsv)
for line in reader:

if reader.line_num == 1:
continue
label_origntemp = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] #升维度
label_origntemp.insert(int(math.floor(float(line[2])/10)),float(math.floor(float(line[2])/10)))
label_orign.append(label_origntemp)
data_orign.append(line[3:])
label_np_arr = np.array(label_orign)
data_np_arr = np.array(data_orign)
#sex_np_arr = np.array(sex_orign)

data_len = data_np_arr.shape[1]
data_num = data_np_arr.shape[0]

#添加层函数
def add_layer(inputs,in_size,out_size,n_layer,activation_function=None):
layer_name='layer%s'%n_layer
with tf.name_scope('layer'):
with tf.name_scope('weights'):
Ws = tf.Variable(tf.random_normal([in_size,out_size]))
tf.histogram_summary(layer_name+'/weights',Ws)
with tf.name_scope('baises'):
bs = tf.Variable(tf.zeros([1,out_size])+0.5)
tf.histogram_summary(layer_name+'/baises',bs)
with tf.name_scope('Wx_plus_b'):
Wxpb = tf.matmul(inputs,Ws) + bs

if activation_function is None:
outputs = Wxpb
else:
outputs = activation_function(Wxpb)
tf.histogram_summary(layer_name+'/outputs',outputs)
return outputs
#比较函数
def compute_accuracy(v_xs,v_ys):
global prediction
y_pre = sess.run(prediction,feed_dict={xs:v_xs})
correct_prediction = tf.equal(tf.argmax(y_pre,1),tf.argmax(v_ys,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
result = sess.run(accuracy,feed_dict={xs:v_xs,ys:v_ys})
return result

# define placeholder for inputs to network
with tf.name_scope('inputs'):
xs = tf.placeholder(tf.float32,[None,data_len])
ys = tf.placeholder(tf.float32,[None,10])

#3个隐藏层
l1 = add_layer(xs,data_len,19,n_layer=1,activation_function=tf.nn.sigmoid)
l2 = add_layer(l1,19,19,n_layer=2,activation_function=tf.nn.sigmoid)
l3 = add_layer(l2,19,19,n_layer=3,activation_function=tf.nn.sigmoid)
# add output layer
prediction = add_layer(l3,19,10,n_layer=4,activation_function=tf.nn.softmax)

with tf.name_scope('loss'):
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1]))
tf.scalar_summary('loss',cross_entropy) #show in evernt
with tf.name_scope('train'):
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy)

init = tf.initialize_all_variables()

saver = tf.train.Saver()
sess = tf.Session()
merged = tf.merge_all_summaries()
writer = tf.train.SummaryWriter("logs/", sess.graph)
sess.run(init)

for i in range(10000):
_, cost = sess.run([train_step, cross_entropy], feed_dict={xs:data_np_arr,
ys:label_np_arr.reshape((data_num,10))})
#sess.run(train_step,feed_dict={xs:data_np_arr,ys:label_np_arr.reshape((data_num,10))})
if i%50 == 0:
print("Epoch:", '%04d' % (i), "cost=", \
"{:.9f}".format(cost),"Accuracy:",compute_accuracy(data_np_arr2,label_np_arr2.reshape((data_num2,10))))
result = sess.run(merged,feed_dict={xs:data_np_arr,
ys:label_np_arr.reshape((data_num,10))})
writer.add_summary(result,i)

print("Optimization Finished!")

训练过程
上传报告

预测

写在最后

陆放翁有诗云:

古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。

此话倒是一点不假,经过这个项目我真的明显的感觉到了我的代码能力的提升。。。 
首先在A1我就困难重重,虽然代码都是现成的(晕。。。),我的电脑中原先装的是python3.x,与python2.x各种不兼容。所以卸了重装才跑起来。 
A2的时候我装的是openCV3,版本库上用的是CV2。。。再加上我刚开学时年少无知,居然装了Ubuntu kylin!各种环境问题,解决一个又来一个,果断重装系统后才终于没有环境问题了。果然Ubuntu14还是比较好的。 
A3开始就需要学习机器学习算法了,因为我之前了解了一些机器学习的相关内容,所以这部分相对轻松了一些。加上我们又站在了巨人的肩膀上,我感觉对于程序员来讲,当了解算法的具体细节遇到困难时,了解已有库的封装和使用方式就变得尤其重要了。我学习的是谷歌的Tensorflow,它在实现神经网络上还是很给力的。对于这个库来说,主要需要了解的是节点、数据流、图等相关概念。想要弄的漂亮的话还可以做一些可视化处理。TensorFlow相对来说还是比较底层的一个库,比如Keras就是一个高层神经网络库,Keras由纯Python编写而成并基于Tensorflow或Theano。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于深度学习神经网络等机器学习技术实现一个医学辅助诊断的专家系统原型 的相关文章

  • C++ 继承学习心得

    单继承 xff1a 一个子类只有一个直接父类时 xff0c 称这个继承关系为单继承 多继承 xff1a 一个子类中有两个或以上直接父类时 xff0c 称这个继承关系为多继承 菱形继承 是一种特殊的继承关系 菱形继承的问题 xff1a 有数据
  • 你的代码放在 GitHub 上,真的安全吗?

    受俄乌冲突的影响 xff0c GitHub 目前正在考虑限制俄罗斯开发人员访问开源代码存储库的可能性 无独有偶 xff0c 早在 2019 年 xff0c GitHub 就曾经因为美国出台贸易制裁国家名单 xff0c 对名单上的国家 地区的
  • ROS进阶学习(一至八)讲

    https blog csdn net weixin 40641902 article list 1 转载自weixin 40641902的博客
  • 如何将Docker升级到最新版本

    CentOS7如何将Docker升级到最新版 如果我们docker的版本比较低的话 xff0c 要怎么才能更新自己docker的版本呢 xff1f 下面是具体的方法 1 查找主机上关于Docker的软件包 rpm qa grep docke
  • 编译Robust Stereo Visual Inertial Odometry for Fast Autonomous Flight

    宾夕法尼亚大学kumar实验室2018年发布 Robust Stereo Visual Inertial Odometry for Fast Autonomous Flight xff0c 基于MSCKF基础上实现双目视觉惯导里程计 刚好这
  • 公网k8s集群搭建史上超详细的教程!!!

    一 背景 xff1a 1 实验背景 x1f9ea 在学习k8s搭建中 xff0c 网上大部分教程都是用虚拟机做单机集群 xff0c 只有极少数是使用服务器搭建教程 xff1b 但是用云服务器搭建的教程中教程版本都比较老 随着时间的推移 xf
  • 【repo/git小技巧】repo sync时报错“The remote end hung up unexpectedly”解决办法

    像往常一样使用repo init gt repo sync 的形式进行代码仓库下载 xff0c 但每次下载repo sync都不能执行成功 xff0c 问题为 The remote end hung up unexpectedly xff0
  • 在 React 中实现记忆以提高性能小技巧

    React 如何渲染 UI 在详细了解 React 中的 memoization 之前 xff0c 让我们先看看 React 如何使用虚拟 DOM 呈现 UI 常规 DOM 基本上包含一组表示为树的节点 DOM 中的每个节点都是 UI 元素
  • 《Linux内核设计与实现》读书总结

    Linux内核设计与实现 进程管理 进程 xff1a 处于执行器的程序 xff0c 包含代码段 xff0c 打开的文件 xff0c 信号 xff0c 内核内部数据 xff0c 内存地址空间 xff0c 多个线程 xff0c 存放全局变量的数
  • python无报错但是主函数没有执行

    python无报错但是主函数没有执行 是不是遇到过python没有报错 xff0c 但是主函数没有执行 xff0c 完全没有结果的情况 遇到这种情况很有可能就是你没有添加if name 61 61 main 这个东西 xff0c 或者格式不
  • 2018.2.2PHPstrom破解版

    作者 xff1a 聽 雨 来源 xff1a CSDN 原文 xff1a https blog csdn net qq 39439751 article details 82758330 版权声明 xff1a 本文为博主原创文章 xff0c
  • python3中 print不加括号报错!

    python 3和python 2的print是有区别 xff0c python3需要加括号 xff0c 但python2不需要 span class token operator gt gt span span class token o
  • leetcode 772 基本计算器3 双栈解析表达式 单调栈

    此题是比较难的一个题 xff0c 不能简单的用递归来做 假设我们已经能把数字分离出来 xff0c 并且解决了其他无关细节 此时我们要考虑 xff0c 如何处理括号和运算优先级 此题最强的一点是 xff0c 当你看到一个符号时 xff0c 你
  • 自然场景OCR检测(YOLOv3+CRNN)

    自然场景OCR检测 YOLOv3 43 CRNN xff08 中文 43 英文模型 xff09 前言 最近对于自然场景下的OCR比较有兴趣 xff0c 所以总结了一些目前OCR现状 xff0c 并且找了一个自然场景OCR的项目练练手 本人新
  • Tx2刷机及安装Jetpack4.5教程

    描述 xff1a 由于项目需要在工控机上运行目标检测程序 xff0c 所需配置需要包括Cuda OpenCV等软件配置 目前Nvidia已经将cuda opencv等相关用于图像处理 深度学习 计算机视觉所需的软件及文件集成到Jetpack
  • ROS gazebo 模型加载报错

    我的ros装的是ros kinetic desktop full版本 xff0c 所以不用另装gazebo 但是用命令 roscore rosrun gazebo ros gazebo 启动后 xff0c 出现如下错误 xff1a Erro
  • excel对比两边数据去重

    需求 筛选重复数据 xff0c A列是1000条数据 xff0c C列是100条数据 xff0c 删除重复的数据 xff0c 只剩900条 首先 xff0c A列数据要分列 xff0c 因为数据格式不一样 xff0c 会导致后面的问题 xf
  • GVIM的配置/使用

    关于GVIM的配置 使用 以我个人喜好配置 配置文件在用户目录下的 vimrc里 配置完后 xff0c 保存并bash一下即可 一 配置 xff1a 根据自己的喜好配置了一点点 colorscheme darkblue span class
  • 小白科研笔记:简析PointRCNN的基于Bin的误差机制

    1 前言 PointRCNN是一篇做3D目标检测的CVPR2019的文章 目前位居KITTI目标检测榜首的是PV RCNN 这个算法的前身就是PointRCNN 它们的作者都是同一个人 考虑到PV RCNN算法有些复杂 xff0c 于是我想
  • ROS基础:获取全局与局部launch Parameter

    在launch 参数配置中 xff0c 分为有全局参数和局部参数 私有参数 xff0c 两者参数的获取是不同的 xff0c 参数示例如下 xff1a lt launch gt lt 全局参数 gt lt param name 61 34 p

随机推荐

  • Redis分布式锁系列

    1 压力测试出的内存泄漏及解决 xff08 可跳过 xff09 使用jmeter对查询产品分类列表接口进行压力测试 xff0c 出现了堆外内存溢出异常 我们设置的虚拟机堆内存100m xff0c 并不是堆外内存100m 产生堆外内存溢出 x
  • java核心技术卷1基础知识整理

    java核心技术卷1基础知识整理 1 java概述2 java程序设计3 对象与类4 继承5 接口 lambda 表达式与内部类6 并发 1 java概述 1 Java 剔除了 C 43 43 中许多很少使用 难以理解 易混淆的特性 xff
  • 【论文笔记】—目标姿态估计—EPro-PnP—2022-CVPR

    论文介绍 该论文被评为 CVPR 2022 最佳学生论文 将PnP位姿优化问题转变为预测位姿概率密度的问题 对于一个基于PnP的物体位姿估计网络 xff0c 可以通过反向传播位姿的概率密度从而学习物体的2D 3D关联 xff0c 实现稳定的
  • STM32 HAL库串口回调函数配置失效(HAL_UART_RxCpltCallback)

    小编实际操作中 xff0c 用HAL UART RxCpltCallback函数配置接收串口数据 xff0c 在测试过程中用手碰了单片机引脚之后无法再接收到数据 xff0c 终于找到了解决办法 xff0c 就是自己使能接收中断和自己定义中断
  • PADS2.4版本,软件打开无法操作问题记录

    小编将pads2 4软件打开后 xff0c 放大和缩小不能使用 xff0c 查找相关资料后汇总方法 xff0c 如果有侵权请联系 xff0c 谢谢 xff0c 解决方法如下 xff1a 方法1 xff1a 设置微软键盘兼容性 xff08 小
  • 学习记录《Simulink 快速入门 —— 官方Help文档》

    Simulink 快速入门 官方Help文档 1 Simulink 模块图2 创建简单模型2 1 打开新模型2 2 打开 Simulink库浏览器2 2 1将模块添加到模型2 2 2 连接模块2 2 3 添加信号查看器2 2 4 运行仿真2
  • 深度学习中的优化问题(Optimization)

    文章目录 1 优化中的挑战1 1 优化问题1 2 挑战1 3 解决方法 2 优化算法2 1 优化算法的分类2 1 1 批量大小的选择2 1 2 学习率调整2 1 3 梯度估计修正 2 2 自适应学习率算法2 2 1 AdaGrad2 2 2
  • 基于MIMO讲解信道估计基本原理

    为什么要进行信道估计 xff1f 信号在通过信道传输的时候 xff0c 会受到信道中种种因素产生的噪声以及可能发生的多径效应 xff0c 弄清信号经过的信道的特性 xff0c 表征信道的技术 过程称为信道估计 xff08 Channel E
  • 基于深度学习Superpoint 的Python图像全景拼接

    pip install opencv python 61 61 3 4 2 16 pip install opencv contrib python 61 61 3 4 2 16 参考 https github com kushalvyas
  • 微分方程的线性化 - 百度文库

    https wk baidu com view aae87102caaedd3383c4d3ca pcf 61 2 amp bfetype 61 new
  • python 中的路径. ./ .. ../

    与Linux系统中一样 xff1a 代表当前所在目录 代表当前所在目录的父目录 代表当前所在目录下的某个文件夹或文件 代表当前所在目录的父目录下的某个文件夹或文件 A B C D E py F 类似于上示的一个目录结构 xff0c 在E p
  • ros的初始化和关闭

    初始化选项 ros init options NoSigintHandler 不安装 SIGINT 句柄 这种情况下你需要自己安装SIGINT句柄来保证节点在退出时候会正确的关闭 SIGINT的默认操作是终结一个进程 xff0c 所以如果你
  • Python报错ModuleNotFoundError: No module named 'numpy'

    Python报错ModuleNotFoundError No module named numpy 这种情况一般是缺少numpy所致 xff0c 需要安装numpy 最好使先进入到进入python 版本安装目录下的Script目录中 xff
  • ubuntu系统查看gcc版本及版本切换

    写在前面 xff1a 自己的测试环境是Ubuntu16 04 xff0c 安装了gcc 5 gcc 7 xff0c 通过下面的方式从实现默认的gcc 5切换到gcc 7 xff0c 亲测有效 xff5e xff5e 1 查看自己当前的gcc
  • ROS中map、odom、base_link坐标系的理解和这三个坐标系在AMCL中的关系

    学了ROS快一年了 xff0c 依旧对map坐标系 odom坐标系 base link坐标系之间的关系不是很清晰 xff0c 这段时间下定决心要捋清楚他们之间的关系 map坐标系 xff1a 地图坐标系 xff0c 是一个固定的坐标系 xf
  • PCL之使用过程中遇到的坑、报错、解决方法

    这篇博客准备记录PCL使用过程中遇到坑 文章目录 1 编译报错 xff1a 96 undefined reference to pcl search Search getName abi cxx11 const 96 解决方法 2 运行报错
  • C++ 报错 error: ‘xxx’ was not declared in this scope

    笔者在做C 43 43 文件的输入输出实验的时候 xff0c 编译时遇到这样一个问题 xff1a error ofstream was not declared span class token keyword in span this s
  • ROS中rosbag相关指令总结

    文章目录 写在前面一 rosbag 基本指令二 bag文件转 txt三 rosbag截取一部分bag四 bag文件生成失败 xff0c 只出现 bag active文件参考链接 xff1a 写在前面 以下内容主要来自官网教程 xff08 h
  • 如何在 Ubuntu 上配置 ROS和LPMS IMU传感器

    最近在ROS上测试 LMPS IMU 传感器 xff0c 在此了一下配置过程 自己的配置环境 xff1a Ubuntu16 04 ROS kinetic LMPS URS2 一 硬件准备 需要的硬件设备 xff1a LPMS URS2 xf
  • 基于深度学习神经网络等机器学习技术实现一个医学辅助诊断的专家系统原型

    3 运行环境搭建 操作系统 xff1a Ubantu xff08 1 xff09 安装python模块 sudo apt get install python pip xff08 2 xff09 安装numpy sudo apt get i