人工智能 实验6.深度学习方法应用(lenet5)

实验六  深度学习方法应用

参考:https://blog.csdn.net/lyq_12/article/details/85051247

一、实验要求

了解MNIST数据集,用lenet5实现手写数字识别

二、实验内容

      请编写lenet网络层,并测得测试集的准确率。

 

三、编写程序调试

import random

import numpy as np

import tensorflow as tf

import matplotlib.pyplot as plt

from sklearn.utils import shuffle

from tensorflow.contrib.layers import flatten

from tensorflow.examples.tutorials.mnist import input_data

 

 

def load_data():

    '''

    导入数据

    :return:训练集、验证集、测试集

    '''

    mnist = input_data.read_data_sets("MNIST_data/", reshape=False)

    X_train, y_train= mnist.train.images, mnist.train.labels

    X_validation, y_validation = mnist.validation.images, mnist.validation.labels

    X_test, y_test= mnist.test.images, mnist.test.labels

 

    assert(len(X_train) == len(y_train))

    assert(len(X_validation) == len(y_validation))

    assert(len(X_test) == len(y_test))

 

    print()

    print("Image Shape: {}".format(X_train[0].shape))

    print()

    print("Training Set:   {} samples".format(len(X_train)))

    print("Validation Set: {} samples".format(len(X_validation)))

    print("Test Set:       {} samples".format(len(X_test)))

 

    # 将训练集进行填充

    # 因为mnist数据集的图片是28*28*1的格式,而lenet只接受32*32的格式

    # 所以只能在这个基础上填充

    X_train = np.pad(X_train, ((0, 0), (2, 2), (2, 2), (0, 0)), 'constant')

    X_validation = np.pad(X_validation, ((0, 0), (2, 2), (2, 2), (0, 0)), 'constant')

    X_test = np.pad(X_test, ((0, 0), (2, 2), (2, 2), (0, 0)), 'constant')

    print("Updated Image Shape: {}".format(X_train[0].shape))

 

 

    # 随机的看一张图

    index = random.randint(0, len(X_train))

    image = X_train[index].squeeze()

    plt.figure(figsize=(1,1))

    plt.imshow(image, cmap="gray")

    plt.show()

    print(y_train[index])

 

    # 打乱数据集的顺序

    X_train, y_train = shuffle(X_train, y_train)

    return  X_train, y_train, X_validation, y_validation,X_test, y_test

四、撰写实验报告

报错

read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.

Instructions for updating:

Please use alternatives such as official/mnist/dataset.py from tensorflow/models.

解决:https://blog.csdn.net/qq_41185868/article/details/88869740

更新说明:使用tensorflow/models中的official/mnist/dataset.py等备选方案。

from tensorflow.examples.tutorials.mnist import input_data

改为

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

numpy.pad

ndarray = numpy.pad(array, pad_width, mode, **kwargs)

array为要填补的数组

pad_width是在各维度的各个方向上想要填补的长度,如((12),(22)),

pad_width——表示每个轴(axis)边缘需要填充的数值数目。

 参数输入方式为:((before_1, after_1), … (before_N, after_N)),其中(before_1, after_1)表示第1轴两边缘分别填充before_1个和after_1个数值。取值为:{sequence, array_like, int}

 

mode为填补类型,即怎样去填补,有“constant”“edge”等模式,如果为constant模式,就得指定填补的值,如果不指定,则默认填充0

•剩下的都是一些可选参数,具体可查看

https://docs.scipy.org/doc/numpy/reference/generated/numpy.pad.html

ndarray为填充好的返回值。

tf.placeholder

placeholder()函数是在神经网络构建graph的时候在模型中的占位,此时并没有把要输入的数据传入模型,它只会分配必要的内存。等建立session,在会话中,运行模型的时候通过feed_dict()函数向占位符喂入数据。

tf.one_hot

tf.one_hot()函数是将input转化为one-hot类型数据输出,相当于将多个数值联合放在一起作为多个相同类型的向量,可用于表示各自的概率分布

one_hot(indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None) Returns a one-hottensor.

indices表示输入的多个数值,通常是矩阵形式;depth表示输出的尺寸。

由于one-hot类型数据长度为depth,其中只用一位数字表示原输入数据,这里的on_value就是这个数字,默认值为1one-hot数据的其他位用off_value表示,默认值为0

 

tf.one_hot()函数规定输入的元素indices0开始,最大的元素值不能超过(depth - 1),因此能够表示(depth + 1)个单位的输入。若输入的元素值超出范围,输出的编码均为 [0, 0 … 0, 0]

 

indices = 0 对应的输出是[1, 0 … 0, 0], indices = 1 对应的输出是[0, 1 … 0, 0], 依次类推,最大可能值的输出是[0, 0 … 0, 1]

tf.truncated_normal

tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)

截断的正态分布中输出随机值。

生成的值服从具有指定平均值和标准偏差的正态分布,如果生成的值大于μ+2σ则丢弃重新选择。

tf.truncated_normal中如果x的取值在区间(μ-2σμ+2σ)之外则重新进行选择。这样保证了生成的值都在均值附近。

 

参数:

shape: 一维的张量,也是输出的张量。

mean: 正态分布的均值。

stddev: 正态分布的标准差。

dtype: 输出的类型。

seed: 一个整数,当设置之后,每次生成的随机数都一样。

name: 操作的名字

tf.nn.conv2d

tf.nn.conv2dTensorFlow里面实现卷积的函数

tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)

除去name参数用以指定该操作的name,与方法有关的一共五个参数:

第一个参数input:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32float64其中之一

第二个参数filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维

第三个参数strides:卷积时在图像每一维的步长,这是一个一维的向量,长度4

第四个参数paddingstring类型的量,只能是"SAME","VALID"其中之一,这个值决定了不同的卷积方式(当其为‘SAME’时,表示卷积核可以停留在图像边缘)

第五个参数:use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true

卷积核以步长滑动遍历全图,结果返回一个Tensor,这个输出,就是我们常说的feature mapshape仍然是[batch, height, width, channels]这种形式。

tf.nn.relu

计算激活函数 relu,即 max(features, 0)。即将矩阵中每行的非最大值置0

tf.nn.max_pool

pooling = tf.nn.max_pool(  

                    h,  

                    ksize=[1, height, width, 1], 

                    strides=[1, 1, 1, 1], 

                    padding='VALID',

                    name="pool")

h :  需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch_size, height, width, channels]这样的shape

k_size : 池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batchchannels上做池化,所以这两个维度设为了1

strides :  窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]

padding: 填充的方法,SAMEVALIDSAME表示添加全0填充,VALID表示不添加

tf.matmul

将矩阵a乘以矩阵b,生成a * b

tf.nn.softmax_cross_entropy_with_logits

计算loss时用

loss是代价值,也就是我们要最小化的值

预测越准确,结果的值越小(别忘了前面还有负号),最后求一个平均,得到我们想要的loss

注意!!!这个函数的返回值并不是一个数,而是一个向量,如果要求交叉熵,我们要再做一步tf.reduce_sum操作,就是对向量里面所有元素求和,最后才得到.

如果求loss,则要做一步tf.reduce_mean操作,对向量求均值

tf.argmax

给出某个tensor对象在某一维上的其数据最大值所在的索引值,常用于metric(如acc)的计算

axis=0时,以列为单位

tf.equal

tf.equal(A, B)是对比这两个矩阵或者向量的相等的元素,如果是相等的那就返回True,反正返回False,返回的值的矩阵维度和A是一样的

tf.cast

cast(

    x,

    dtype,

    name=None

)

x的数据格式转化成dtype.例如,原来x的数据格式是bool 
那么将其转化成float以后,就能够将其转化成01的序列。反之也可以

with tf.Session() as sess:

参考:https://blog.csdn.net/wwwlyj123321/article/details/86064772

一个Session可能会拥有一些资源,例如Variable或者Queue。当我们不再需要该session的时候,需要将这些资源进行释放

sess.run(tf.global_variables_initializer())#global_variables_initializer返回一个用来初始化 计算图中 所有global variable oprun 所有global Variable assign op

sess.run

sess.run(fetchesfeed_dict)

///这个是让fetches节点动起来,告诉tensorflow,想要此节点的输出。

///fetches 可以是list或者tensor向量

///feed_dict。替换原图中的某个tensor

 

sess.run() 中的feed_dict

 

我们都知道feed_dict的作用是给使用placeholder创建出来的tensor赋值。其实,他的作用更加广泛:feed 使用一个 值临时替换一个 op 的输出结果. 你可以提供 feed 数据作为 run() 调用的参数. feed 只在调用它的方法内有效, 方法结束, feed 就会消失.

TF Saver 保存/加载训练好模型(网络+参数)

训练时候保存:

# Create a saver.
saver = tf.train.Saver(...variables...)
# Remember the training_op we want to run by adding it to a collection.
tf.add_to_collection('train_op', train_op)
sess = tf.Session()
for step in xrange(1000000):
    sess.run(train_op)
    if step % 1000 == 0:
        # Saves checkpoint, which by default also exports a meta_graph
        # named 'my-model-global_step.meta'.
        saver.save(sess, 'my-model', global_step=step)

 

加载模型训练好的的网络和参数来测试,或进一步训练

with tf.Session() as sess:

  new_saver = tf.train.import_meta_graph('my-model.meta')

  new_saver.restore(sess,tf.train.latest_checkpoint( './')

tensorflow模型主要包含网络的结构的定义或者叫graph和训练好的网络结构里的参数。

因此tensorflow model包含2个文件:

aMeta graph:

使用protocol buffer来保存整个tensorflow graph.例如所有的variables, operations, collections等等。这个文件使用.meta后缀

 

b) Checkpoint file:

二进制文件包含所有的weights,biases,gradients和其他variables的值。这个文件使用.ckpt后缀,后来变成有2个文件:

mymodel.data-00000-of-00001

mymodel.index

 

第一个文件.data文件就是保存训练的variables我们将要使用它。

和这些文件一起,tensorflow还有一个文件叫checkpoint用来简单保存最近一次保存checkpoint文件的记录

实验代码

import random
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
from tensorflow.contrib.layers import flatten
#from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets


def load_data():
    '''
    导入数据
    :return:训练集、验证集、测试集
    '''
#    mnist = input_data.read_data_sets("MNIST_data/", reshape=False)
    mnist = read_data_sets("MNIST_data/", reshape=False)
    X_train, y_train= mnist.train.images, mnist.train.labels
    X_validation, y_validation = mnist.validation.images, mnist.validation.labels
    X_test, y_test= mnist.test.images, mnist.test.labels

    assert(len(X_train) == len(y_train))
    assert(len(X_validation) == len(y_validation))
    assert(len(X_test) == len(y_test))

    print()
    print("Image Shape: {}".format(X_train[0].shape))
    print()
    print("Training Set:   {} samples".format(len(X_train)))
    print("Validation Set: {} samples".format(len(X_validation)))
    print("Test Set:       {} samples".format(len(X_test)))

    # 将训练集进行填充
    # 因为mnist数据集的图片是28*28*1的格式,而lenet只接受32*32的格式
    # 所以只能在这个基础上填充
    X_train = np.pad(X_train, ((0, 0), (2, 2), (2, 2), (0, 0)), 'constant')
    X_validation = np.pad(X_validation, ((0, 0), (2, 2), (2, 2), (0, 0)), 'constant')
    X_test = np.pad(X_test, ((0, 0), (2, 2), (2, 2), (0, 0)), 'constant')
    print("Updated Image Shape: {}".format(X_train[0].shape))


    # 随机的看一张图
    index = random.randint(0, len(X_train))
    image = X_train[index].squeeze()# 从数组的形状中删除单维条目,即把shape中为1的维度去掉
    plt.figure(figsize=(1,1))
    plt.imshow(image, cmap="gray")
    plt.show()
    print("number:",y_train[index])

    # 打乱数据集的顺序
    X_train, y_train = shuffle(X_train, y_train)
    return  X_train, y_train, X_validation, y_validation,X_test, y_test
#SOLUTION: Implement LeNet-5
def LeNet(x):    
    # Arguments used for tf.truncated_normal, randomly defines variables for the weights and biases for each layer
#    用于tf.truncated_normal的参数, 随机定义每个图层的权重和偏差的变量
    mu=0
    sigma=0.1
    # SOLUTION: Layer 1: Convolutional.卷积 Input = 32x32x1. Output = 28x28x6.
    conv1_W=tf.Variable(tf.truncated_normal(shape=(5, 5, 1, 6), mean = mu, stddev = sigma))#tf.truncated_normal从截断的正态分布中输出随机值。
    conv1_b=tf.Variable(tf.zeros(6))#tf.Variable(initializer,name)initializer是初始化参数
    conv1=tf.nn.conv2d(x, conv1_W, strides=[1, 1, 1, 1], padding='VALID') + conv1_b#卷积函数
    # SOLUTION: Activation.
    conv1 = tf.nn.relu(conv1)#计算激活函数 relu,即 max(features, 0)。即将矩阵中每行的非最大值置0。
    # SOLUTION: Pooling. Input = 28x28x6. Output = 14x14x6.
    conv1=tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
    # SOLUTION: Layer 2: Convolutional. Output = 10x10x16.
    conv2_W=tf.Variable(tf.truncated_normal(shape=(5, 5, 6, 16), mean = mu, stddev = sigma))
    conv2_b=tf.Variable(tf.zeros(16))
    conv2=tf.nn.conv2d(conv1, conv2_W, strides=[1, 1, 1, 1], padding='VALID') + conv2_b
    # SOLUTION: Activation.
    conv2=tf.nn.relu(conv2)
    # SOLUTION: Pooling. Input = 10x10x16. Output = 5x5x16.
    conv2=tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
    # SOLUTION: Flatten. Input = 5x5x16. Output = 400.
    fc0=flatten(conv2)#平化降维
    # SOLUTION: Layer 3: Fully Connected全连接层. Input = 400. Output = 120.
    fc1_W = tf.Variable(tf.truncated_normal(shape=(400, 120), mean = mu, stddev = sigma))
    fc1_b = tf.Variable(tf.zeros(120))
    fc1   = tf.matmul(fc0, fc1_W) + fc1_b#matmul将矩阵a乘以矩阵b(不是对应元素相乘),生成a * b。
    
    # SOLUTION: Activation.
    fc1    = tf.nn.relu(fc1)
 
    # SOLUTION: Layer 4: Fully Connected. Input = 120. Output = 84.
    fc2_W  = tf.Variable(tf.truncated_normal(shape=(120, 84), mean = mu, stddev = sigma))
    fc2_b  = tf.Variable(tf.zeros(84))
    fc2    = tf.matmul(fc1, fc2_W) + fc2_b
    
    # SOLUTION: Activation.
    fc2    = tf.nn.relu(fc2)
 
    # SOLUTION: Layer 5: Fully Connected. Input = 84. Output = 10.
    fc3_W  = tf.Variable(tf.truncated_normal(shape=(84, 10), mean = mu, stddev = sigma))
    fc3_b  = tf.Variable(tf.zeros(10))
    logits = tf.matmul(fc2, fc3_W) + fc3_b
     
    return logits
 
    
EPOCHS=10
BATCH_SIZE=128
X_train, y_train, X_validation, y_validation,X_test, y_test=load_data()
x=tf.placeholder(tf.float32, (None, 32, 32, 1))
#y=tf.placeholder(tf.int32, (None))
#one_hot_y=tf.one_hot(y, 10)
y=tf.placeholder(tf.int32, (None))#在模型中的占位
one_hot_y=tf.one_hot(y, 10)#one_hot(indices, depth)
 
#Training Pipeline
rate=0.001
logits=LeNet(x)
cross_entropy=tf.nn.softmax_cross_entropy_with_logits(labels=one_hot_y, logits=logits)
#print("cross_entropy:",cross_entropy)
loss_operation=tf.reduce_mean(cross_entropy)
optimizer=tf.train.AdamOptimizer(learning_rate = rate)#寻找全局最优点的优化算法,引入了二次方梯度校正。
training_operation=optimizer.minimize(loss_operation)

 
#Model Evaluation模型评估
correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(one_hot_y, 1))#argmax某一维上的其数据最大值所在的索引值
accuracy_operation = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
saver = tf.train.Saver()

def evaluate(X_data, y_data):
    num_examples = len(X_data)
    total_accuracy = 0
    sess = tf.get_default_session()#返回当前线程的默认会话
    for offset in range(0, num_examples, BATCH_SIZE):
        batch_x, batch_y = X_data[offset:offset+BATCH_SIZE], y_data[offset:offset+BATCH_SIZE]
        accuracy = sess.run(accuracy_operation, feed_dict={x: batch_x, y: batch_y})
        total_accuracy+= (accuracy * len(batch_x))
    return total_accuracy / num_examples


 
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())#global_variables_initializer返回一个用来初始化 计算图中 所有global variable的 op。run了 所有global Variable 的 assign op
    num_examples = len(X_train)
    
    print("Training...")
    print()
    for i in range(EPOCHS):
        X_train, y_train=shuffle(X_train, y_train)#随机排序
        for offset in range(0, num_examples, BATCH_SIZE):
            end=offset+BATCH_SIZE
            batch_x, batch_y=X_train[offset:end], y_train[offset:end]
            sess.run(training_operation,feed_dict={x: batch_x, y: batch_y})
#            loss, acc = sess.run(training_operation,feed_dict={x: batch_x, y: batch_y})
#            print("Step " + str(offset) + ", Minibatch Loss= " + \
#                  "{:.4f}".format(loss) + ", Training Accuracy= " + \
#                  "{:.3f}".format(acc))
        validation_accuracy=evaluate(X_validation, y_validation)
        print("EPOCH {} ...".format(i+1))
        print("Validation Accuracy = {:.3f}".format(validation_accuracy))
        print()
    saver.save(sess, './lenet')
    print("Model saved")
    
    
#Evaluate the Model    
with tf.Session() as sess:
    saver.restore(sess, tf.train.latest_checkpoint('.'))#加载模型训练好的的网络和参数来测试,或进一步训练
    test_accuracy = evaluate(X_test, y_test)
    print("Test Accuracy = {:.3f}".format(test_accuracy))

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值