TensorFlow CNN卷积神经网络实现工况图分类识别(一)

1. Tensorflow知识点

1.1. 张量

在Tensorflow程序中,所有的数据都是通过张量的形式来表示。从功能的角度上看,张量可以简单的理解为多维数组。
(1)占位符Placeholder
可以把占位符看作为函数的未知数。假设函数f(x)=wx,其中w是3行2列的矩阵,
w = [ 1 2 3 4 5 6 ] w=\begin{bmatrix} 1 &2 \\ 3 &4 \\ 5 &6 \end{bmatrix} w=135246
那么x只要满足行数为2,列数不定的矩阵就可以了。
例如,本案例中x = tf.placeholder("float", shape=[None, 160 * 120 * 3]),输入变量的占位符是3个数的乘积57600。
(2)Variable对象
Variable类用于存储随时变化的值,创建Variable对象后,要调用tf.global_variables_initializer(),才可以使用Variable对象的值。
(3)张量基本运算
本案例用到乘法:关于矩阵(二维张量)乘法函数为matmul,例如:tf.matmul(h_pool3_flat, W_fc1)
(4)张量Reduction
TensorFlow提供了几个操作,您可以使用这些操作执行常见的数学计算,以减少张量的各种维。本案例中用到:
reduce_sum(),压缩求和,对于多维数组元素的相加,如果不指定是进行哪一维度的相加,结果是未定义的。tensorflow指定了默认行为:把所有元素全加在一起。
例如:

# 'x' is [[1, 1, 1]]
#         [1, 1, 1]]
tf.reduce_sum(x) ==> 6
tf.reduce_sum(x, 0) ==> [2, 2, 2]
tf.reduce_sum(x, 1) ==> [3, 3]

reduce_mean(), 函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的的平均值,主要用作降维或者计算tensor(图像)的平均值。
例如:

# 'x' is [[1., 1. ]]
#         [2., 2.]]
tf.reduce_mean(x) ==> 1.5
tf.reduce_mean(x, 0) ==> [1.5, 1.5]
tf.reduce_mean(x, 1) ==> [1.,  2.]

(5)其他张量函数
argmax(),tf.argmax是tensorflow用numpy的np.argmax实现的,它能给出某个tensor对象在某一维上的其数据最大值所在的索引值,tf.argmax()函数中有个axis参数(轴),该参数能指定按照哪个维度计算。如在矩阵的结构中,axis可被设置为0或1,分别表示:0—按列计算,1—行计算。例如:tf.argmax(y_conv,1)

equal(),比较两个张量是否相等,是逐个元素进行判断,如果相等就是 True,不相等,就是 False。例如:correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))

cast(),把比较结果转换为浮点型,例如:tf.cast(correct_prediction, "float")

1.2. 运行模型——会话

Tensorflow中使用会话(session)来执行定义好的运算。会话拥有并管理程序运行时的所有资源。会话使用有两种模式。
第一种模式:需要明确调用会话生成函数和关闭会话函数,手动管理所有资源。

sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
for i in range(200):
    batch = mnist.train.next_batch(50)
    if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
        print ("step {}, training accuracy {}".format(i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
sess.close()

注:参考mnist手写数字识别示例。

第二种模式:通过Python上下文管理器的机制,将所有的计算放到“with”的内部,自行管理所有资源。

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    filelist = get_data_filename('mydata')
    ......     
        if i%50 == 0:
            train_accuracy = accuracy.eval(feed_dict={x:batch_x, y_: batch_y, keep_prob: 1.0})
            print ("step {}, training accuracy {}".format(i, train_accuracy))
        train_step.run(feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.5})

2. 卷积网络模型

2.1. 神经元概述

在这里插入图片描述
将上述的神经元结构抽象成数学概念,可以得到如上图所示的神经元模型。

  • 模型的输入是数据里的自变量,比如图中的x1、x2、x3。它们用圆点表示,对应着神经元里的树突。
  • 接收输入变量的是一个线性模型,在图中用正方形表示。这个线性模型对应着神经元的细胞体。对于神经元中的线性模型,用 w i w_{i} wi表示权重,用b表示截距, ∑ i 3 w i x i + b \sum_{i}^{3}w_{i}x_{i} + b i3wixi+b
  • 接下来是一个非线性的激活函数 f ( ) f() f()(activation function),它将控制是否对外发送信号,如图中用三角形表示,对应这神经元里的轴突。在神经网络领域,常常用一个圆圈来概括地表示线性模型和激活函数。
  • 将模型的各个部分联结起来得到最后的输出 f ( ∑ i 3 w i x i + b ) f(\sum_{i}^{3}w_{i}x_{i} + b) f(i3wixi+b),这个值将传递给下一个神经元模型,在图中用箭头表示,对应着神经元里的突触。

在神经元模型中,非线性的激活函数是整个模型的核心。例如本案例中使用的是激活函数 ReLU。神经元模型代码如下:

# 增加第二层全连接
W_fc2 = weight_variable([512,256])
b_fc2 = bias_variable([256])
h_fc2 = tf.nn.relu(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)

在深度学习中,常用的激活函数主要有:sigmoid函数,tanh函数,ReLU函数等。例如本案例使用的是ReLU函数。
nn.relu(),函数的作用是计算激活函数 ReLU,即 max(features, 0)。即将矩阵中每行的非最大值置0。例如:h_fc2 = tf.nn.relu(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)
在这里插入图片描述
r e l u ( x ) = m a x ( x , 0 ) = { x , x ⩾ 0 0 x &lt; 0 relu(x)=max(x,0)= \left\{\begin{matrix} x, &amp; x\geqslant 0\\ 0 &amp; x&lt;0 \end{matrix}\right. relu(x)=max(x,0)={x,0x0x<0

2.2. 网络结构

卷积网络模型基于LeNet-5模型,使用3层卷积(卷积层和池化层)和3层全连接层。
在这里插入图片描述

序号输入输出
1输入层输入图像和标签160×120×3(RGB图像,3个通道)
2第一卷积层x=[-1,120,160,3], W=[3, 3, 3, 16], strides=[1, 1, 1, 1], padding=‘SAME’160×120×3,3个特征(通道)
3第一池化层x=[-1,120,160,3], ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding=‘SAME’80×60×16,16个特征(通道)
4第二卷积层x=[-1,60,80,16], W=[3, 3, 16, 32], strides=[1, 1, 1, 1], padding=‘SAME’80×80×32,32个特征(通道)
5第二池化层x=[-1,60,80,16], ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding=‘SAME’40×30×32,32个特征(通道)
6第三卷积层x=[-1,30,40,32], W=[3, 3, 32, 64], strides=[1, 1, 1, 1], padding=‘SAME’40×30×32,32个特征(通道)
7第三池化层x=[-1,30,40,32], ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding=‘SAME’)20×15×64,64个特征(通道)
8第一全连接层x=[-1,20×15×64], W=[20×15×64, 512]512神经元
9第二全连接层x=[-1,512], W=[512, 256]256神经元
10第三全连接层x=[-1,256], W=[256, 4]4个输出值

损失函数,nn.softmax()
如上图所示,全连接最后输出(full3),使用了softmax损失函数,TensorFlow中,Softmax回归参数被去掉,它只是一层额外的处理层,将神经网络的输出变成了一个概率分布。
假设经过第三层(full3)全连接网络输出为 y 1 , y 2 , . . . , y n y_{1},y_{2},...,y_{n} y1,y2,...,yn,那么经过Softmax回归处理之后的输出为:
s o f t m a x ( y ) i = y i ′ = e y i ∑ j = 1 n e y i softmax(y)_{i}=y_{i}^{&#x27;}=\frac{e^{y_{i}}}{\sum_{j=1}^{n}e^{y_{i}}} softmax(y)i=yi=j=1neyieyi
从以上公式可以看出,损失函数的输出是概率。本案例的代码如下:
y_conv=tf.nn.softmax(tf.matmul(h_fc2_drop, W_fc3) + b_fc3,name='y_conv')

交叉熵
假设p代表正确答案,q代表预测值,交叉熵用来描述两个概率分布的距离,也就是说交叉熵值越小,两个概率分布越接近,表示为: H = ∑ i = 1 n y i l o g ( y i ′ ) H=\sum_{i=1}^{n}y_{i}log(y^{&#x27;}_{i}) H=i=1nyilog(yi),其中 y i y_{i} yi为真实值, y i ′ y^{&#x27;}_{i} yi为预测值。例如本案例中的代码如下:
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))

2.3. 卷积及网络操作

(1)卷积操作

设矩形图像尺寸为W×H,卷积核的尺寸为FxF,步幅为S,图像深度(通道数)为C,Padding使用P,则卷积后输出图像大小:
W 1 = W 0 − F + 2 P S + 1 W_{1} = \frac{W_{0} - F + 2P}{S} + 1 W1=SW0F+2P+1 H 1 = H 0 − F + 2 P S + 1 H_{1} = \frac{H_{0} - F + 2P}{S} + 1 H1=SH0F+2P+1

注意:Padding的作用用于解决图像边缘信息损失的问题。
本文案例中,卷积核尺寸为3x3,S(步长)= 1 。

如卷积核为3时 padding 选择1
如卷积核为5时 padding 选择2
如卷积核为7时 padding 选择3

(2)池化操作

设输入图像尺寸为WxH,其中W为图像宽,H为图像高,D:图像深度(通道数),卷积核的尺寸为FxF,S为步长,则池化后输出图像大小:
W 1 = W 0 − F + S + 1 W_{1} = \frac{W_{0} - F +}{S} + 1 W1=SW0F++1 H 1 = H 0 − F S + 1 H_{1} = \frac{H_{0} - F}{S} + 1 H1=SH0F+1

注:本文案例中,卷积核尺寸为2x2,S(步长)= 2。

3. 模型训练

随着工业互联网高速发展,工业大数据人工智能应运而生,通过探索,发现工业生产中,大量物联网数据形成的工况监控图,存在人工识别标准不统一、学习周期长等情况,先前所开发的极限值、趋势对比等监控软件效果差,需要人工智能技术来提高识别效率和准确率。

3.1. 输入数据

输入是石油工业采油生产工况——示功图,来自物联网采集数据所绘制的示功图。本次实验采用部分数据,分类如下:0-正常,1- 抽油杆断,2- 供液不足,3- 气影响。
在这里插入图片描述

3.2. 训练参数

学习率设置为1e-4,batch_size为50。

每个分类样本数为1000,学习率分别是1e-4、5e-5情况下,batch size分别是50、100的情况下,测试准确率接近80%。如果增加样本,优化模型和学习算法,很容易达到90%以上。

3.3. 训练结果

在这里插入图片描述

import tensorflow as tf
import cv2
import os
import numpy as np

# 创建大量的权重和偏置项。这个模型中的权重在初始化时应该加入少量的噪声来打破对称性以及避免0梯度。
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.01)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.01, shape=shape)
    return tf.Variable(initial)
# 卷积使用1步长(stride size),0边距(padding size)的模板,保证输出和输入是同一个大小。
# 我们的池化用简单传统的2x2大小的模板做max pooling。为了代码更简洁,我们把这部分抽象成一个函数。
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')

batch_size = 10
learning_rate=1e-5 #学习率
#占位符,通过为输入图像和目标输出类别创建节点,来开始构建计算图。
x = tf.placeholder("float", shape=[None, 160 * 120 * 3]) #图片像素160*120
y_ = tf.placeholder("float", shape=[None, 4])
# 输入图片x是一个2维的浮点数张量。这里,分配给它的shape为[None, 160 * 120 * 3],其中160 * 120 * 3是一张展平的图片的维度。
# None表示其值大小不定,在这里作为第一个维度值,用以指代batch的大小,意即x的数量不定。
# 输出类别值y_也是一个2维张量,其中每一行为一个4维的one-hot向量,用于代表对应某一图片的类别。

# 第一层卷积,由一个卷积接一个max pooling完成。
# 卷积在每个3x3的patch中算出16个特征。卷积的权重张量形状是[3, 3, 3, 16],前两个维度是patch的大小,接着是输入的通道数目,最后是输出的通道数目。
#  而对于每一个输出通道都有一个对应的偏置量。
W_conv1 = weight_variable([3, 3, 3, 16])
b_conv1 = bias_variable([16])

# 把x变成一个4d向量,其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数(因为是rgb彩色所以这里是3,如果是灰度图这里的通道数为1)
x_image = tf.reshape(x, [-1,120,160,3])

# 把x_image和权值向量进行卷积,加上偏置项,然后应用ReLU激活函数,最后进行max pooling。
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

# 为了构建一个更深的网络,我们会把几个类似的层堆叠起来。第二层中,每个3x3的patch会得到32个特征。
W_conv2 = weight_variable([3, 3, 16, 32])
b_conv2 = bias_variable([32])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

#第三层卷积
W_conv3 = weight_variable([3, 3, 32, 64])
b_conv3 = bias_variable([64])

h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)
h_pool3 = max_pool_2x2(h_conv3)

# 现在,图片尺寸减小到15x20,我们加入一个有512个神经元的全连接层,用于处理整个图片。
# 我们把池化层输出的张量reshape成一些向量,乘上权重矩阵,加上偏置,然后对其使用ReLU。
W_fc1 = weight_variable([15 * 20 * 64, 512]) 
b_fc1 = bias_variable([512]) 

h_pool3_flat = tf.reshape(h_pool3, [-1, 15*20*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool3_flat, W_fc1) + b_fc1)

# Dropout,为了减少过拟合,我们在输出层之前加入dropout。
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# 增加第二层全连接
W_fc2 = weight_variable([512,256])
b_fc2 = bias_variable([256])
h_fc2 = tf.nn.relu(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)

h_fc2_drop = tf.nn.dropout(h_fc2,keep_prob)

'''softmax层,根据256个特征计算输出标签'''
# 输出层,我们添加一个softmax层,就像前面的单层softmax regression一样。
W_fc3 = weight_variable([256, 4]) 
b_fc3 = bias_variable([4])

y_conv=tf.nn.softmax(tf.matmul(h_fc2_drop, W_fc3) + b_fc3,name='y_conv')  # softmax层,计算输出标签

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
# 使用TensorFlow内置的交叉熵函数避免出现权重消失问题
#cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_, logits=y_conv))
# tf.reduce_sum :计算tensor指定轴方向上的所有元素的累加和;
# tf.reduce_mean 函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的的平均值,主要用作降维或者计算tensor(图像)的平均值。
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

saver = tf.train.Saver()  #定义saver

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print("开始训练!")
    filelist = get_data_filename('mydata')
    lenth = len(filelist)
    k = 0

    for i in range(int(lenth/3)):
        # 每个batch为50组数据,梯度下降
        batch_x,batch_y = get_batch(filelist,k*batch_size,batch_size)
        k +=1
        if k*batch_size>=lenth:
            k = 0 
                     
        if i%50 == 0:
            train_accuracy = accuracy.eval(feed_dict={x:batch_x, y_: batch_y, keep_prob: 1.0})
            print ("step {}, training accuracy {}".format(i, train_accuracy))
        train_step.run(feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.5})
    
    saver.save(sess, 'D:/06Study/Workspace/Python/Machine Learning/SAVE/model.ckpt') #模型储存位置
    
    print("开始测试!")
    filelist = get_data_filename('testdata')
    lenth = int(len(filelist)/100)
    for i in range(lenth):
        x_test_batch,y_test_batch  = get_batch(filelist,i*100,100)

        print ("test accuracy {}".format(accuracy.eval(feed_dict={x: x_test_batch, y_: y_test_batch, keep_prob: 1.0})))

代码中提到的“get_batch”函数,是需要自行收集图片,组织数据,本文不提供数据。可以参考[2]中人脸数据。关于模型的使用、数据的准备、集成模型等内容,后续再总结。
由于作者水平有限,初入人工智能,欢迎一起讨论、指导。

参考:

[1]《面向机器学习专家的 MNIST 高级教程》 Tensorflow中文社区
[2]《TensorFlow CNN卷积神经网络实现人脸性别检测》 Github, linzhong 2018.12
[3]《使用Python Matplotlib绘制用于CNN训练图片的方法及实践》 CSDN博客, 肖永威 2019.03
[4]《Windows10(64bit)环境下Python3 + Tensorflow安装》 CSDN博客, 肖永威 2018.08
[5]《使用Python Matplotlib绘图并输出图像到文件中的实践》 CSDN博客, 肖永威 2018.04
[6]《Tensorflow卷积神经网络(CNN)手写数字识别示例学习》 CSDN博客, 一颗贪婪的星 2018.05
[7]《TensorFlow实战Google深度学习框架》(第2版)电子工业出版社 郑泽宇 梁博文 顾思宇 著 2018.02
[8]《图解深度学习与神经网络》 电子工业出版社 张平 编著 2018.10
[9]《图像卷积和池化操作后的特征图大小计算方法》 CSDN博客, ZJE_ANDY 2018.12
[10]《神经网络(一):神经元模型与逻辑回归》 简书 tgbaggio 2018.09
[11]《使用Python科学计算包搭建CNN算法实践(1》 CSDN博客, 肖永威 2018.05

  • 2
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
是的,TensorFlow可以使用卷积神经网络CNN)来实现MNIST手写数字识别CNN是一种在像处理和计算机视觉领域非常流行的神经网络结构,可以有效地提取像中的特征并进行分类。 在TensorFlow中,可以使用tf.keras API构建CNN模型。以下是一个简单的CNN模型示例,用于识别MNIST手写数字: ``` python import tensorflow as tf # 加载MNIST数据集 mnist = tf.keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() # 对数据进行预处理 x_train, x_test = x_train / 255.0, x_test / 255.0 # 构建CNN模型 model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), activation='relu'), tf.keras.layers.Flatten(), tf.keras.layers.Dense(64, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ]) # 编译模型 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(x_train.reshape(-1, 28, 28, 1), y_train, epochs=5, validation_data=(x_test.reshape(-1, 28, 28, 1), y_test)) # 评估模型 model.evaluate(x_test.reshape(-1, 28, 28, 1), y_test) ``` 该模型包括三个卷积层和两个全连接层,其中每个卷积层后面跟随一个最大池化层。该模型可以在MNIST测试集上达到约99%的准确率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖永威

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值