天天看点

深度学习之卷积神经网络(CNN) — 理论与代码结合

往期回顾:

神经网络之卷积和池化(一)

神经网络之卷积和池化(二)

卷积神经网络之全连接层

CNN架构:

深度学习之卷积神经网络(CNN) — 理论与代码结合

利用CNN对时尚产品进行分类

首先,导入库

import warnings
warnings.filterwarnings('ignore')
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
           

然后,读取数据。数据集是在 tendorflow.examples中提供的,可以直接读取数据:

from tensorflow.examples.tutorials.mnist import input_data
fashion_mnist = input_data.read_data_sets('data/fashion/', one_hot=True)
           

结果为:

Extracting data/fashion/train-images-idx3-ubyte.gz
Extracting data/fashion/train-labels-idx1-ubyte.gz
Extracting data/fashion/t10k-images-idx3-ubyte.gz
Extracting data/fashion/t10k-labels-idx1-ubyte.gz
           

接下来,查看数据内容:

print("No of images in training set {}".format(fashion_mnist.train.images.shape))
print("No of labels in training set {}".format(fashion_mnist.train.labels.shape))

print("No of images in test set {}".format(fashion_mnist.test.images.shape))
print("No of labels in test set {}".format(fashion_mnist.test.labels.shape))
           

结果为:

No of images in training set (55000, 784)
No of labels in training set (55000, 10)
No of images in test set (10000, 784)
No of labels in test set (10000, 10)
           

已知有10种类别的产品,那么可以对产品进行标记:

labels = {
 0: 'T-shirt/top',
 1: 'Trouser',
 2: 'Pullover',
 3: 'Dress',
 4: 'Coat',
 5: 'Sandal',
 6: 'Shirt',
 7: 'Sneaker',
 8: 'Bag',
 9: 'Ankle boot'
}
           

这时,观察一些图像:

img1 = fashion_mnist.train.images[41].reshape(28,28)
# 由one-hot编码数据获得相应的整型标签
label1 = np.where(fashion_mnist.train.labels[41] == 1)[0][0]
# 绘制样本
print("y = {} ({})".format(label1, labels[label1]))
plt.imshow(img1, cmap='Greys')
           

输出和可视化图像如图所示:

y = 6 (Shirt)

深度学习之卷积神经网络(CNN) — 理论与代码结合

接着需要构建一个CNN,将所有这些图像各自分类。在此,对输入图像和输出标记定义占位符。由于输入图像大小为784,因此定义输入x的占位符如下:

这时,需要将输入重新组织为 [p,q,r,s] 格式,其中,q和r是输入图像的实际大小,即28x28,s为通道个数。由于只有灰度图像,所以s为1。p是指训练样本个数,即批大小。由于批大小未知,可设为-1,并在训练过程中动态改变:

由于有10种不同的标签,在此定义输出的占位符如下:

现在,需要定义一个称为conv2d的函数,用于执行卷积运算,即输入矩阵x与滤波矩阵w按元素相乘,且步幅为1,SAME填充。

设strides=[1,1,1,1]。步幅中的第一个值和最后一个值设为1,这意味着不会在训练样本和不同通道中移动。第二个值和第三个值设为1,表明滤波器在高度和宽度方向上移动一个像素:

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
           

定义一个函数maxpool2d来执行池化操作。在此,执行最大池化,且步幅为2,SAME填充。Ksize是指池化窗口的形状:

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

接下来,定义权重和偏置。在此,将构建一个包含两个卷积层,即一个全连接层和一个输出层的CNN,因此,需定义所有这些层的权重。这些权重实际上就是卷积层中的滤波器。

为此,初始化权重矩阵为

[filter_shape[0],filter_shape[1],number_of_input_channel,filter_size]

在此,采用一个5x5的滤波器,且设滤波器大小为32。由于是灰度图像,输入通道数为1。由此,权重矩阵为

[5,5,1,32]

在第二个卷积层中,是取第1个卷积层的输入(为32)作为输出通道,因此,与下一层相连的输入通道数为32:

接着,初始化偏置:

b_c1 = tf.Variable(tf.random_normal([32]))
b_c2 = tf.Variable(tf.random_normal([64]))
           

现在,在第1个卷积层上执行运算,即对输入x执行ReLU激活函数的卷积运行,然后是最大池化操作:

conv1 = tf.nn.relu(conv2d(x_shaped, w_c1) + b_c1)
conv1 = maxpool2d(conv1)
           

这时,第一个卷积层的结果将传递到下一个卷积层,在此,对第1个卷积的结果再执行ReLU激活函数的卷积运算,然后是最大池化操作:

conv2 = tf.nn.relu(conv2d(conv1, w_c2) + b_c2)
conv2 = maxpool2d(conv2)
           

经过两个卷积层的卷积运算和池化操作,输入图像将会从28x28x1减少采样到7x7x1。在将其输入到全连接层之前,需要进行扁平化。然后,第2个卷积层的结果输入到全连接层,接着乘以权重,增加偏置,并应用ReLU激活函数:

x_flattened = tf.reshape(conv2, [-1, 7*7*64])
w_fc = tf.Variable(tf.random_normal([7*7*64,1024]))
b_fc = tf.Variable(tf.random_normal([1024]))
fc = tf.nn.relu(tf.matmul(x_flattened,w_fc)+ b_fc)
           

现在,需要定义输出层的权重和偏置,具体为 [ 当前层中神经元的个数,下一层中神经元的个数 ]:

w_out = tf.Variable(tf.random_normal([1024, 10]))
b_out = tf.Variable(tf.random_normal([10]))
           

通过将全连接层的结果乘以权重,并增加偏置可得到输出。执行softmax激活函数即可得到该输出的概率:

output = tf.matmul(fc, w_out)+ b_out
yhat = tf.nn.softmax(output)
           

定义损失函数为交叉熵损失。在此利用一个称为Adam优化器的新型优化器来最小化损失,而不是梯度下降优化器:

learning_rate = 0.01
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=output, labels=y))
optimiser = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cross_entropy)
           

接下来,计算accuracy:

correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(yhat, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
           

并定义超参数:

epochs = 10
batch_size = 100
           

这时,启动Tensorflow会话,构建模型:

init_op = tf.global_variables_initializer()

with tf.Session() as sess:
   sess.run(init_op)
   total_batch = int(len(fashion_mnist.train.labels) / batch_size)
    # For each epcoh
   for epoch in range(epochs):
        
        avg_cost = 0
        for i in range(total_batch):
            batch_x, batch_y = fashion_mnist.train.next_batch(batch_size=batch_size)
            
            _, c = sess.run([optimiser, cross_entropy], 
                         feed_dict={x: batch_x, y: batch_y})
            
            avg_cost += c / total_batch
            
        print("Epoch:", (epoch + 1), "cost =""{:.3f}".format(avg_cost))
        
   print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))
           

7.13 Classifying Fashion Products Using CNN.ipynb

继续阅读