机器学习算法 09—05 Tensorflow代码实现Softmax回归_模型的保存与加载_模块化_代码实现DNN对手写数字进行识别

1. 理解Placeholder

总结:shape指定所要传入数据的类型

dtype=tf.float32 将int类型转为浮点型 将“4” 数值字符串转为浮点型

import tensorflow as tf

# 让我们修改前面的代码去实现Mini-Batch梯度下降
# 为了去实现这个,我们需要一种方式去取代X和y在每一次迭代中,使用一小批数据
# 最简单的方式去做到这个是去使用placeholder节点
# 这些节点特点是它们不真正的计算,它们只是在执行过程中你要它们输出数据的时候去输出数据
# 它们会传输训练数据给TensorFlow在训练的时候
# 如果在运行过程中你不给它们指定数据,你会得到一个异常

# 需要做的是使用placeholder()并且给输出的tensor指定数据类型,也可以选择指定形状
# 如果你指定None对于某一个维度,它的意思代表任意大小
A = tf.placeholder(dtype=tf.float32, shape=(None, 3))
B = A + 5

with tf.Session() as sess:
    B_val_1 = B.eval(feed_dict={A: [[1, 2, 3]]})
    B_val_2 = B.eval(feed_dict={A: [['4', 5, 6],
                                    [7, 8, 9]]})

print(B_val_1)
print(B_val_2)


2.Tensorflow实现Softmax回归

多分类一般使用交叉熵损失函数:

公式:Cross-Entropy=-\sum_{i}^{m}y_{i}lna_{i}     

yi是真实值(概率),ai是预测值(概率)

对于采用One_hot编码的数据,如手写数字识别,除了m个样本外,每个样本都给出了10个预测值概率和真实值概率

此时的公式为:

Cross-Entropy=\sum_{i}^{m}\sum_{j=0}^{9}y_{ij}lna_{ij}

实现流程

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名: 12_Softmax_regression.py

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import matplotlib.pyplot as plt

__author__ = 'bowen'

# mn.SOURCE_URL = "http://yann.lecun.com/exdb/mnist/"
my_mnist = input_data.read_data_sets("MNIST_data_bak/", one_hot=True)
# print(my_mnist.train.images.shape,my_mnist.train.labels)  # 可以看一下图片的类型
"""
总共有55000张图片   每张图片有28*28=784个像素点(单通道的) 第一张图片的数字是[0. 0. 0. ... 1. 0. 0.]=7 因为用了one_hot=True
(55000, 784) [[0. 0. 0. ... 1. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 ...
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 1. 0.]]

 one_hot=False
 (55000, 784) [7 3 4 ... 5 6 8]
"""
# 可以打印出图片
# first=my_mnist.train.images[0].reshape(28,28)
# plt.imshow(first,cmap=plt.cm.gray) #cmap=plt.cm.gray 打印灰色图片
# plt.show()

# The MNIST data is split into three parts:
# 55,000 data points of training data (mnist.train)
# 10,000 points of test data (mnist.test), and
# 5,000 points of validation data (mnist.validation). #验证集

# Each image is 28 pixels by 28 pixels

# 输入的是一堆图片,None表示不限输入条数,784表示每张图片都是一个784个像素值的一维向量
# 所以输入的矩阵是None乘以784二维矩阵
x = tf.placeholder(dtype=tf.float32, shape=(None, 784))
# 初始化都是0,二维矩阵784乘以10个W值
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

y_pred = tf.nn.softmax(tf.matmul(x, W) + b)

# 训练
# labels是每张图片都对应一个one-hot的10个值的向量
y = tf.placeholder(dtype=tf.float32, shape=(None, 10))
# 定义损失函数,交叉熵损失函数

# 对于多分类问题,通常使用交叉熵损失函数
# reduction_indices等价于axis,指明按照每行加,还是按照每列加 [0]按照行+ [1]按照列+ 得到# 的结果是m行1列的 tf.reduce_sum 完成的是0-9列的结合(内层加和)
# tf.reduce_mean() 是将m行1列的加和 求平均
# y*tf.log(y_pred)是矩阵中数值对应位置相乘  m 行10列 *m行10列 得到一个m行10列的矩阵

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y * tf.log(y_pred), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

# 评估

# tf.argmax()是一个从tensor中寻找最大值的序号,
# tf.argmax就是求各个预测的数字中概率最大的那一个
correct_prediction = tf.equal(tf.argmax(y_pred, 1),tf.argmax(y, 1))  
# y是一个m行10列的  经过one—hot编码的  argmax(y, 1)的 1 表示方向,表示按列比较,
# 对于y来说因为采用了one_hot编码,其实就是每张图片数字on——hot 1所在位置的索引值,其实也就是手写数字的真实值
# tf.equal()的到是m行一列的 true或者false值向量

# 用tf.cast将之前correct_prediction输出的bool值转换为float32,再求平均
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 初始化变量
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for _ in range(10000):
    batch_xs, batch_ys = my_mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})
    print("TrainSet batch acc : %s  " % accuracy.eval({x: batch_xs, y: batch_ys}))
    print("ValidSet acc : %s" % accuracy.eval({x: my_mnist.validation.images, y: my_mnist.validation.labels}))

# 测试
print("TestSet acc : %s" % accuracy.eval({x: my_mnist.test.images, y: my_mnist.test.labels}))

# 总结
# 1,定义算法公式,也就是神经网络forward时的计算
# 2,定义loss,选定优化器,并指定优化器优化loss
# 3,迭代地对数据进行训练
# 4,在测试集或验证集上对准确率进行评测

精度求解

3. 模型的保存与加载

3.1 保存模型

# 有时候需要把模型保存起来,
# 有时候需要做一些checkpoint在训练中  以致于如果计算机宕机,我们还可以从之前checkpoint的位置去继续
# TensorFlow使得我们去保存和加载模型非常方便,仅需要去创建Saver节点在构建阶段最后
# 然后在计算阶段去调用save()方法

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

__author__ = 'yasaka'

# mn.SOURCE_URL = "http://yann.lecun.com/exdb/mnist/"
my_mnist = input_data.read_data_sets("MNIST_data_bak/", one_hot=True)

# The MNIST data is split into three parts:
# 55,000 data points of training data (mnist.train)
# 10,000 points of test data (mnist.test), and
# 5,000 points of validation data (mnist.validation).

# Each image is 28 pixels by 28 pixels

# 输入的是一堆图片,None表示不限输入条数,784表示每张图片都是一个784个像素值的一维向量
# 所以输入的矩阵是None乘以784二维矩阵
x = tf.placeholder(dtype=tf.float32, shape=(None, 784))
# 初始化都是0,二维矩阵784乘以10个W值
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)

# 训练
# labels是每张图片都对应一个one-hot的10个值的向量
y_ = tf.placeholder(dtype=tf.float32, shape=(None, 10))
# 定义损失函数,交叉熵损失函数
# 对于多分类问题,通常使用交叉熵损失函数
# reduction_indices等价于axis,指明按照每行加,还是按照每列加
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),
                                              reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

# 初始化变量
init = tf.global_variables_initializer()
# 创建Saver()节点
saver = tf.train.Saver()

n_epoch = 1000

with tf.Session() as sess:
    # 不要忘记利用session初始化一些变量
    # sess.run(init)
    ckpt=tf.train.get_checkpoint_state('./ckpt') #获取一下是否有这个文件夹  以及这个文件夹是否有内容;如果没有这个ckpt文件夹 就会返回None
    if ckpt and ckpt.model_checkpoint_path:
        print("hello")
        print(ckpt.model_checkpoint_path)
        saver.restore(sess,ckpt.model_checkpoint_path) #ckpt.model_checkpoint_path这个是一个路径字符串  把他保存到sess中
        print("hello bias %s"%sess.run(b))
    else:
        print("word")
        sess.run(tf.global_variables_initializer())

    for epoch in range(n_epoch):
        if epoch % 100==0:
            print("%s bias %s"%(epoch,sess.run(b)))
            save_path=saver.save(sess,"./ckpt/my_mode.ckpt",global_step=epoch)  #把sess在clpt文件夹下 保存成my_mode.ckpt文件
        batch_xs, batch_ys = my_mnist.train.next_batch(100)
        sess.run(train_step,feed_dict={x:batch_xs,y_:batch_ys})
    save_path=saver.save(sess,"./ckpt/my_model_final.ckpt")

 总结:1. saver.save()方法需要传入一个session参数,然后是路径。

 3.2 加载模型

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

__author__ = 'bowen'

# mn.SOURCE_URL = "http://yann.lecun.com/exdb/mnist/"
my_mnist = input_data.read_data_sets("MNIST_data_bak/", one_hot=True)

# The MNIST data is split into three parts:
# 55,000 data points of training data (mnist.train)
# 10,000 points of test data (mnist.test), and
# 5,000 points of validation data (mnist.validation).

# Each image is 28 pixels by 28 pixels

# 输入的是一堆图片,None表示不限输入条数,784表示每张图片都是一个784个像素值的一维向量
# 所以输入的矩阵是None乘以784二维矩阵
x = tf.placeholder(dtype=tf.float32, shape=(None, 784))
# 初始化都是0,二维矩阵784乘以10个W值
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)
# labels是每张图片都对应一个one-hot的10个值的向量
y_ = tf.placeholder(dtype=tf.float32, shape=(None, 10))

saver = tf.train.Saver()

with tf.Session() as sess:
    saver.restore(sess, "./ckpt/my_model_final.ckpt")
    # 评估
    # tf.argmax()是一个从tensor中寻找最大值的序号,tf.argmax就是求各个预测的数字中概率最大的那一个
    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))

    # 用tf.cast将之前correct_prediction输出的bool值转换为float32,再求平均
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    # 测试
    print(accuracy.eval({x: my_mnist.test.images, y_: my_mnist.test.labels}))



4.DNN对手写数字进行识别

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
from tensorflow.contrib.layers import fully_connected


# 构建图阶段
n_inputs = 28*28
n_hidden1 = 300
n_hidden2 = 100
n_hidden3 = 50
n_outputs = 10

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name='X')
y = tf.placeholder(tf.int64, shape=(None), name='y')

"""
# 构建神经网络层,我们这里两个隐藏层,基本一样,除了输入inputs到每个神经元的连接不同
# 和神经元个数不同
# 输出层也非常相似,只是激活函数从ReLU变成了Softmax而已
def neuron_layer(X, n_neurons, name, activation=None):
    # 包含所有计算节点对于这一层,name_scope可写可不写
    with tf.name_scope(name):
        # 取输入矩阵的维度作为层的输入连接个数
        n_inputs = int(X.get_shape()[1])
        stddev = 2 / np.sqrt(n_inputs)
        # 这层里面的w可以看成是二维数组,每个神经元对于一组w参数
        # truncated normal distribution 比 regular normal distribution的值小
        # 不会出现任何大的权重值,确保慢慢的稳健的训练
        # 使用这种标准方差会让收敛快
        # w参数需要随机,不能为0,否则输出为0,最后调整都是一个幅度没意义
        init = tf.truncated_normal((n_inputs, n_neurons), stddev=stddev)
        w = tf.Variable(init, name='weights')
        b = tf.Variable(tf.zeros([n_neurons]), name='biases')
        # 向量表达的使用比一条一条加和要高效
        z = tf.matmul(X, w) + b
        if activation == "relu":
            return tf.nn.relu(z)
        else:
            return z


with tf.name_scope("dnn"):
    hidden1 = neuron_layer(X, n_hidden1, "hidden1", activation="relu")
    hidden2 = neuron_layer(hidden1, n_hidden2, "hidden2", activation="relu")
    # 进入到softmax之前的结果
    logits = neuron_layer(hidden2, n_outputs, "outputs")
"""

with tf.name_scope("dnn"):
    # tensorflow使用这个函数帮助我们使用合适的初始化w和b的策略,默认使用ReLU激活函数
    hidden1 = fully_connected(X, n_hidden1, scope="hidden1")
    hidden2 = fully_connected(hidden1, n_hidden2, scope="hidden2")
    hidden3 = fully_connected(hidden2, n_hidden3, scope="hidden3")
    logits = fully_connected(hidden3, n_outputs, scope="outputs", activation_fn=None)

with tf.name_scope("loss"):
    # 定义交叉熵损失函数,并且求个样本平均
    # 函数等价于先使用softmax损失函数,再接着计算交叉熵,并且更有效率
    # 类似的softmax_cross_entropy_with_logits只会给one-hot编码,我们使用的会给0-9分类号
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(xentropy, name="loss")

learning_rate = 0.01

with tf.name_scope("train"):
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    training_op = optimizer.minimize(loss)

with tf.name_scope("eval"):
    # 获取logits里面最大的那1位和y比较类别好是否相同,返回True或者False一组值
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))

init = tf.global_variables_initializer()
saver = tf.train.Saver()

# 计算图阶段
mnist = input_data.read_data_sets("MNIST_data_bak/")
n_epochs = 400
batch_size = 50

with tf.Session() as sess:
    init.run()
    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run([training_op], feed_dict={X: X_batch, y: y_batch})
        acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
        acc_test = accuracy.eval(feed_dict={X: mnist.test.images,
                                            y: mnist.test.labels})
        print(epoch, "Train accuracy:", acc_train, "Test accuracy:", acc_test)

    save_path = saver.save(sess, "./my_dnn_model_final.ckpt")
'''
# 使用模型预测
with tf.Session as sess:
    saver.restore(sess, "./my_dnn_model_final.ckpt")
    X_new_scaled = [...]
    Z = logits.eval(feed_dict={X: X_new_scaled})
    y_pred = np.argmax(Z, axis=1)  # 查看最大的类别是哪个
'''

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值