基于tensorflow搭建一个简单的CNN模型(code)


我们将要搭建一个简单的卷积神经网络结构去提高手写数字的预测结果精度。

# Introductory CNN Model: MNIST Digits

# In this example, we will download the MNIST handwritten

# digits and create a simple CNN network to predict the

# digit category (0-9)

主要分为以下几个步骤:导入数据;创建模型的变量;搭建模型;采用批量化训练网络;可视化loss,accuracy等结果。


1.导入必要的库和开始一个图谱会话

import tensorflow as tf

import numpy as np

import matplotlib as plt

from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets

sess = tf.Session()

2.导入数据集和将图片装换为28 * 28大小的矩阵

data_dir = 'temp'   #数据集存放的文件夹

mnist = read_data_sets(data_dir)      #读取数据集

#将训练和测试数据集图片归一化为28*28大小

train_xdata = np.array([np.reshape(x, (28,28)) for x in mnist.train.images])

test_xdata = np.array([np.reshape(x, (28,28)) for x in mnist.test.images])

train_labels = mnist.train.labels    #训练数据集标签

test_labels = mnist.test.labels       #测试数据集标签

3.定义模型参数

batch_size = 100       #一个批量的图片数量

learning_rate = 0.005           #学习率

evaluation_size = 500          #模型验证数据集一个批量的数量

image_width = train_xdata[0].shape[0]      #图片的长 28

image_height = train_xdata[0].shape[1]     #图片的宽 28

target_size = max(train_labels)+1    #输出类别的个数 10

num_channels = 1                             # 通道数为1

generations = 500                              #迭代代数

eval_every = 5                                    #每次5个generation

conv1_features = 25                          #卷积核的个数

conv2_features = 50                          #卷积核的个数

max_pool_size1 = 2                          #池化层窗口大小

max_pool_size2 = 2                          #池化层窗口大小

fully_connected_size1 = 100            #全连接层大小

4.定义数据集的占位符

#输入数据的张量大小

x_input_shape = (batch_size, image_width, image_height, num_channels)

#创建输入训练数据的占位符

x_input = tf.placeholder(tf.float32, shape=x_input_shape)         

#创建一个批量训练结果的占位符

y_target = tf.placeholder(tf.int32, shape=batch_size)         

#验证图片输入张量

eval_input_shape = (evaluation_size, image_width, image_height,num_channels)

#创建输入验证数据的占位符

eval_input = tf.placeholder(tf.float32, shape=eval_input_shape)    

#创建一个批量验证结果的占位符

eval_target = tf.placeholder(tf.int32, shape= evaluation_size )  

5.定义训练权重和偏置的变量

#定义第一个卷积核的参数,其中用tf.truncated_normal生成正太分布的数据,#stddev(正态分布标准差)为0.1

conv1_weight = tf.Variable(tf.truncated_normal([4, 4, num_channels, conv1_features], stddev=0.1, dtype = tf.float32))

#定义第一个卷积核对应的偏置

conv1_bias = tf.Variable(tf.zeros([conv1_features], dtype=tf.float32))

#定义第二个卷积核的参数,其中用tf.truncated_normal生成正太分布的数据,#stddev(正态分布标准差)为0.1

conv2_weight = tf.Variable(tf.truncated_normal([4, 4, num_channels, conv2_features], stddev=0.1, dtype = tf.float32))

#定义第二个卷积核对应的偏置

conv2_bias = tf.Variable(tf.zeros([conv2_features], dtype=tf.float32))

6.定义全连接层的权重和偏置

#输出卷积特征图的大小

resulting_width = image_width // (max_pool_size1 * max_pool_size2)

resulting_height = image_height // (max_pool_size1 * max_pool_size2)

#将卷积层特征图拉成一维向量

full1_input_size = resulting_width * resulting_height * conv2_features

#创建第一个全连接层权重和偏置

full1_weight =tf.Variable(tf.truncated_normal([full1_input_size,fully_connected_size1],

                                               stddev=0.1, dtype=tf.float32))

full1_bias = tf.Variable(tf.truncated_normal([fully_connected_size1], stddev=0.1,

                                               dtype=tf.float32))

#创建第二个全连接层权重和偏置

full2_weight = tf.Variable(tf.truncated_normal([fully_connected_size1,target_size],

                                               stddev=0.1, dtype=tf.float32))

full2_bias = tf.Variable(tf.truncated_normal([target_size], stddev=0.1,

                                               dtype=tf.float32))

7.定义网络模型

def my_conv_net(input_data):

    #First Conv-relu-maxpool layer

    conv1 = tf.nn.conv2d(input_data, conv1_weight, strides=[1, 1, 1, 1], padding='SAME')

    relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_bias))

    max_pool1 = tf.nn.max_pool(relu1, ksize=[1, max_pool_size1, max_pool_size1, 1],  strides=[1, max_pool_size1, max_pool_size1, 1], padding='SAME')

    # Second Conv-relu-maxpool layer

    conv2 = tf.nn.conv2d(max_pool1, conv2_weight, strides=[1, 1, 1, 1], padding='SAME')

    relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_bias))

    max_pool2 = tf.nn.max_pool(relu2, ksize=[1, max_pool_size1, max_pool_size1, 1],  strides=[1, max_pool_size2, max_pool_size2, 1], padding='SAME')

    #将输出转换为一个[1xN],为下一个全连接层输入做准备

    final_conv_shape = max_pool2.get_shape().as_list()

    final_shape = final_conv_shape[1] * final_conv_shape[2] * final_conv_shape[3]

    flat_output = tf.reshape(max_pool2, [final_conv_shape[0], final_shape])

    #First fully-connected layer

    fully_connected1 = tf.nn.relu(tf.add(tf.add(tf.matmul(flat_output,full1_weight), full1_bias)))

    # Second fully-connected layer

    final_model_output = tf.add(tf.matmul(fully_connected1, full2_weight), full2_bias)

    return (final_model_output)

8.定义网络的训练数据和测数据

model_output = my_conv_net(x_input)

test_model_output = my_conv_net(eval_input)

9.使用Softmax函数作为loss function

loss = loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=model_output, labels=y_target))

10.接下来创建一个训练和测试的函数

prediction = tf.nn.softmax(model_output)

test_prediction = tf.nn.softmax(test_model_output)

# Create accuracy function

def get_accuracy(logits, targets):

    batch_predictions = np.argmax(logits, axis=1)

    num_correct = np.sum(np.equal(batch_predictions, targets))

return(100. * num_correct/batch_predictions.shape[0])

11.创建一个optimizer function

my_optimizer = tf.train.MomentumOptimizer(learning_rate, 0.9)

train_step = my_optimizer.minimize(loss)

# Initialize Variables

init = tf.initialize_all_variables()

sess.run(init)

12.开始训练模型

train_loss = [ ]

train_acc = [ ]

test_acc = [ ]

for i in range(generations):

    rand_index = np.random.choice(len(train_xdata), size=batch_size)

    rand_x = train_xdata[rand_index]

    rand_x = np.expand_dims(rand_x, 3)

    rand_y = train_labels[rand_index]

    train_dict = {x_input: rand_x, y_target: rand_y}

    sess.run(train_step, feed_dict=train_dict)

    temp_train_loss, temp_train_preds = sess.run([loss, prediction], feed_dict=train_dict)

    temp_train_acc = get_accuracy(temp_train_preds, rand_y)

    if (i+1) % eval_every == 0:

        eval_index = np.random.choice(len(test_xdata), size=evaluation_size)

        eval_x = test_xdata[eval_index]

        eval_x = np.expand_dims(eval_x, 3)

        eval_y = test_labels[eval_index]

        test_dict = {eval_input: eval_x, eval_target: eval_y}

        test_preds = sess.run(test_prediction, feed_dict=test_dict)

        temp_test_acc = get_accuracy(test_preds, eval_y)

        # Record and print results

        train_loss.append(temp_train_loss)

        train_acc.append(temp_train_acc)

        test_acc.append(temp_test_acc)

        acc_and_loss = [(i+1), temp_train_loss, temp_train_acc, temp_test_acc]

        acc_and_loss = [np.round(x,2) for x in acc_and_loss]

13.输出结果

print('Generation # {}. Train Loss: {:.2f}. Train Acc (Test Acc): {:.2f} ({:.2f})'.format(*acc_and_loss))

14.使用matplotlib显示loss-accuracies曲线

eval_indices = range(0, generations, eval_every)

# Plot loss over time

plt.plot(eval_indices, train_loss, 'k-')

plt.title('Softmax Loss per Generation')

plt.xlabel('Generation')

plt.ylabel('Softmax Loss')

plt.show()

# Plot train and test accuracy

plt.plot(eval_indices, train_acc, 'k-', label='Train Set Accuracy')

plt.plot(eval_indices, test_acc, 'r--', label='Test Set Accuracy')

plt.title('Train and Test Accuracy')

plt.xlabel('Generation')

plt.ylabel('Accuracy')

plt.legend(loc='lower right')

plt.show()

图1. 左图是我们500 generations时的训练精度曲线。右图是在500 generations时的softmax loss值

15.显示最新一个批量的预测结果

# Plot the 6 of the last batch results:

actuals = rand_y[0:6]

predictions = np.argmax(temp_train_preds,axis=1)[0:6]

images = np.squeeze(rand_x[0:6])

Nrows = 2

Ncols = 3

for i in range(6):

    plt.subplot(Nrows, Ncols, i+1)

    plt.imshow(np.reshape(images[i], [28,28]), cmap='Greys_r')

    plt.title('Actual: ' + str(actuals[i]) + ' Pred: ' + str(predi

    ctions[i]),fontsize=10)

    frame = plt.gca()

    frame.axes.get_xaxis().set_visible(False)

    frame.axes.get_yaxis().set_visible(False)

图2. 显示出6张随机图片的真实结果和预测结果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容