tensorflow学习文档

这篇博客介绍了TensorFlow的基础用法,包括加法操作、平面拟合的示例,重点讲解了使用TensorFlow进行MNIST手写数字识别的步骤,包括数据下载、单层全连接模型和卷积神经网络模型的训练,以及模型的保存与调用。在MNIST识别中,卷积神经网络模型达到了98%的测试准确率。
部署运行你感兴趣的模型镜像

下面用几个小例子来学习TensorFlow的用法。

1. 第一个程序:加法

import tensorflow as tf
# 两个常量操作
a = tf.constant(5)
b = tf.constant(8)
# 一个add() 操作
sum = tf.add(a, b)
# 会话
sess = tf.Session()
# 在会话中执行操作
result = sess.run(sum)
print(result)
sess.close()

这里简单演示了用tensorflow进行一个加法运算。

2. 第二个程序:平面拟合

import tensorflow as tf
import numpy as np

x_data = np.float32(np.random.rand(2, 100)) # 随机输入100个二维平面上的点[x1, x2]
y_data = np.dot([0.100, 0.200], x_data) + 0.300 # y = 0.1*x1 + 0.2*x2 + 0.3
# 构造一个线性模型
#
b = tf.Variable(tf.zeros([1]))
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b  # y = W*x + b
# 最小化方差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss) # 使loss降到
# 初始化变量操作
init_op = tf.global_variables_initializer()
# 启动图 (graph)
sess = tf.Session()
sess.run(init_op)
# 拟合平面
for step in range(0, 201):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(W), sess.run(b))

这个程序向展示了如何学习参数。我们先用numpy初始化了100个二维数据点[x1 ,x2], 我们令y_data = 0.1*x1 + 0.2*x2 + 0.3

现在假设我们只知道100个(x1, x2)这样的点和与它们对应的y值y_data,我们想求y_data 与(x1, x2)的关系式。那么我们假设y = w1*x1 + w2*x2 + b = (w1, w2) * (x1, x2) + b, 现在我们给(w1, w2)和b一个初始值,并用次初始值计算y的值,这样计算值y和真实值y_data之间就会有一个误差loss,这个误差loss是一个大于零的数,它是由w1, w2, b引起的。然后我们定义一个优化器optimizer来优化loss,就是不断改变w1, w2, b可以使loss减小。从下图可以看出,随着step的增加,loss在减小,(w1, w2)和b在向(0.1, 0.2)和0.3靠近。


3.  MNIST 手写数字识别例子

(1) 数据集下载:mnist数据集

(2) 训练代码示例1:单层全连接 模型

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

# 保存mnist数据的文件路径
MNIST_data_folder = 'D:/mnist/data'
log_dir = 'D:/mnist/logs/fc_10000steps'
mnist = input_data.read_data_sets(MNIST_data_folder, one_hot=True)

# 定义一个“图”
myGraph = tf.Graph()
with myGraph.as_default():
    with tf.name_scope("Img_Label_Input"):
        #占位符,存储训练数据和标签
        x = tf.placeholder("float", shape=[None, 784])
        y_ = tf.placeholder("float", shape=[None, 10])

    with tf.name_scope("Fully_Connected_Layer"):
        W = tf.Variable(tf.zeros([784, 10]))
        b = tf.Variable(tf.zeros([10]))

        logits = tf.matmul(x, W) + b

        # 计算y, 这里y是一个1x10的矩阵,代表为0-9的概率
        y = tf.nn.softmax(logits)

        # 将w和b添加到summary中
        tf.summary.histogram('W', W)
        tf.summary.histogram('b', b)

    with tf.name_scope("Training"):
        # 这里用交叉熵作为损失函数,他可以衡量计算所得的y和真实的标签y_的分布差别
        cross_entropy = -tf.reduce_sum(y_ * tf.log(y))

        # 用优化器降低损失函数
        train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

        tf.summary.scalar("Cross_entropy", cross_entropy)

    with tf.name_scope("Evaluation"):
        # 识别正确的数量
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        # 计算准确率
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

        tf.summary.scalar("Accuracy", accuracy)

# 会话启动图
with tf.Session(graph=myGraph) as sess:
    # 初始化所有变量
    sess.run(tf.global_variables_initializer())
    saver = tf.train.Saver()
    merged_op = tf.summary.merge_all()
    summary_writer = tf.summary.FileWriter(log_dir, graph=sess.graph)

    for step in range(10000):
        # 获取一批训练数据, 这里是100副图片的数据
        batch_x, batch_y = mnist.train.next_batch(100)
        # 将训练数据feed给占位符,运行会话进行训练
        train_step.run(feed_dict={x: batch_x, y_: batch_y})

        if step % 500 == 0:
            summary, loss = sess.run([merged_op, cross_entropy], feed_dict={x: batch_x, y_: batch_y})
            summary_writer.add_summary(summary, step)
            print("step:", step, "cross_entropy:", loss)

        if step % 1000 == 0: # 保存检查点
            checkpoint_file = os.path.join(log_dir, 'checkpoint')
            saver.save(sess, checkpoint_file + '.ckpt')

    # 用测试集进行测试识别准确率
    print("accuracy:", accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

这个是一个简单的单层全连接神经网络模型,将数据输入后经过一层全连接层输出。最后在测试集上的准确率在91%左右。

(3) 训练代码示例2:卷积神经网络+全连接 模型

# encoding=utf-8
import os.path
import numpy as np
import tensorflow as tf
import cv2
from tensorflow.examples.tutorials.mnist import input_data


flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_float('learning_rate', 1e-4, 'Initial learning rate.')
flags.DEFINE_integer('max_steps', 501, 'Number of steps to run trainer.')
flags.DEFINE_integer('hidden1', 128, 'Number of units in hidden layer 1.')
flags.DEFINE_integer('hidden2', 32, 'Number of units in hidden layer 2.')
flags.DEFINE_integer('batch_size', 100, 'Batch size.  '
                                        'Must divide evenly into the dataset sizes.')
flags.DEFINE_string('data_dir', 'D:/mnist/data', 'Directory to put the training data.')
flags.DEFINE_string('log_dir', 'D:/mnist/logs/conv_10000steps', 'Dirtory to put the log files')

mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)

# 用于初始化权重参数
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

# 用于初始化偏置参数
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

# 构建图
myGraph = tf.Graph()
with myGraph.as_default():
    with tf.name_scope('Img_Label_Input'):
        # 占位符
        x_raw = tf.placeholder(tf.float32, shape=[None, 784], name="image_input")
        y = tf.placeholder(tf.float32, shape=[None, 10], name="label_input")

    with tf.name_scope('Conv1'):
        # 将数据从1*784的矩阵形式还原成28x28的矩阵(图片)形式
        x = tf.reshape(x_raw, shape=[-1, 28, 28, 1])
        # 权重参数
        W_conv1 = weight_variable([5, 5, 1, 32])
        # 偏置参数
        b_conv1 = bias_variable([32])
        # 进行卷积运算,图像长宽不变,“通道” 为32, 即为28x28x32, 并对它进行“激活”
        l_conv1 = tf.nn.relu(tf.nn.conv2d(x, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1)
        # 进行池化运算, 图像长宽变为原来的一半, 通道数不变,即为14x14x32
        l_pool1 = tf.nn.max_pool(l_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

        # 将图片数据添加到summary中,最多保存10张
        tf.summary.image('x_input', x, max_outputs=10)
        tf.summary.histogram('W_con1', W_conv1)
        tf.summary.histogram('b_con1', b_conv1)

    with tf.name_scope('Conv2'):
        W_conv2 = weight_variable([5, 5, 32, 64])
        b_conv2 = bias_variable([64])
        # 卷积长宽不变,“通道” 为64, 即为14x14x64,
        l_conv2 = tf.nn.relu(tf.nn.conv2d(l_pool1, W_conv2, strides=[1, 1, 1, 1], padding='SAME') + b_conv2)
        # 进行池化运算, 图像长宽变为原来的一半, 通道数不变,即为7x7x64
        l_pool2 = tf.nn.max_pool(l_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

        tf.summary.histogram('W_con2', W_conv2)
        tf.summary.histogram('b_con2', b_conv2)

    with tf.name_scope('Fully_Connected_Layer1'):
        W_fc1 = weight_variable([64 * 7 * 7, 1024])
        b_fc1 = bias_variable([1024])
        # 将数据从7x7x64的“图片”转化为7x7x64的矩阵
        l_pool2_flat = tf.reshape(l_pool2, [-1, 64 * 7 * 7])
        # 进行全连接运算,结果是1024的矩阵,并对它进行激活
        l_fc1 = tf.nn.relu(tf.matmul(l_pool2_flat, W_fc1) + b_fc1)
        # 占位符
        keep_prob = tf.placeholder(tf.float32, name="keep_prob")
        # 让一部分神经元“失活”
        l_fc1_drop = tf.nn.dropout(l_fc1, keep_prob)

        tf.summary.histogram('W_fc1', W_fc1)
        tf.summary.histogram('b_fc1', b_fc1)

    with tf.name_scope('Fully_Connected_Layer2'):
        W_fc2 = weight_variable([1024, 10])
        b_fc2 = bias_variable([10])

        # 输出
        logits = tf.matmul(l_fc1_drop, W_fc2) + b_fc2
        y_ = tf.nn.softmax(logits=logits, name="class_prob")

        tf.summary.histogram('W_fc2', W_fc1)
        tf.summary.histogram('b_fc2', b_fc1)

    with tf.name_scope('training'):
        cross_entropy = -tf.reduce_sum(y * tf.log(y_))
        train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize(cross_entropy)
        correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name="accuracy")

        tf.summary.scalar('loss', cross_entropy)
        tf.summary.scalar('accuracy', accuracy)

with tf.Session(graph=myGraph) as sess:
    sess.run(tf.global_variables_initializer())
    saver = tf.train.Saver()

    merged = tf.summary.merge_all()
    summary_writer = tf.summary.FileWriter(FLAGS.log_dir, graph=sess.graph)

    for step in range(FLAGS.max_steps):
        batch = mnist.train.next_batch(100)
        sess.run(train_step, feed_dict={x_raw: batch[0], y: batch[1], keep_prob: 0.5})
        if step % 20 == 0:
            train_accuracy = accuracy.eval(feed_dict={x_raw: batch[0], y: batch[1], keep_prob: 1.0})
            print('step %d training accuracy:%g' % (step, train_accuracy))
            summary = sess.run(merged, feed_dict={x_raw: batch[0], y: batch[1], keep_prob: 1.0})
            summary_writer.add_summary(summary, step)
        if step % 50 == 0:
            checkpoint_file = os.path.join(FLAGS.log_dir, 'checkpoint')
            saver.save(sess, checkpoint_file, global_step=step)

    test_accuracy = accuracy.eval(feed_dict={x_raw: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
    print('test accuracy:%g' % test_accuracy)

    # 用图片做测试
    img = cv2.imread("/home/ysl/图片/digits/digit1.png", 0)
    cv2.imshow("test", img)
    arr1 = np.reshape((img.astype(np.float32) / 255.0), (1, 784))
    # 把预处理后图片作为输入,进行分类预测

    # 结果是十个类的概率
    res_y = tf.matmul(l_fc1_drop, W_fc2) + b_fc2
    # 取最大
    res = tf.argmax(res_y, 1)

    print("Result:", res_y.eval(feed_dict={x: arr1, keep_prob: 1.0}))
    print("Predect Result: ", res.eval(feed_dict={x: arr1, keep_prob: 1.0}))

这个模型包含两个卷积层和两个全连接层,在测试集上的准确率在98%左右。我们也可以把自己的手写数字图片处理后作为输入,测试模型识别的准确率。

(4) 将模型参数保存下来

我们需要将计算机辛辛苦苦训练的模型的参数保存下来,方便调用。

import os, argparse
import tensorflow as tf
from tensorflow.python.framework import graph_util

# 定义一个保存图参数的函数
def freeze_graph(input_checkpoint, output_graph):
    # freeze之前必须明确我们想要哪些模型中的数据
    # 输出结点可以看我们模型的定义
    # 只有定义了输出结点, freeze才会把得到输出结点所必要的结点都保存下来,或者哪些结点可以丢弃!
    # 所以,output_node_names必须根据不同的网络进行修改
    output_node_names = "Fully_Connnected_Layer2/class_prob,Training/accuracy"

    # We clear the devices, to allow TensorFlow to control on the loading where it wants operations to be calculated
    clear_devices = True

    # We import the meta graph and retrive a Saver
    saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=clear_devices)

    # We retrieve the protobuf graph definition
    graph = tf.get_default_graph()
    input_graph_def = graph.as_graph_def()

    # 我们开启一个会话,并且加载检查点文件
    # 这边已经将训练好的模型参数加载进来
    # 相当于将参数已经固化在了图当中
    with tf.Session() as sess:
	saver.restore(sess, input_checkpoint)

	# 使用tensorflow内置方法把模型中的参数变量转换为常量
	output_graph_def = graph_util.convert_variables_to_constants(sess, input_graph_def, output_node_names.split(
			","))  

	# Finally we serialize and dump the output graph to the filesystem
	with tf.gfile.GFile(output_graph, "wb") as f:
		f.write(output_graph_def.SerializeToString())
		print("%d ops in the final graph." % len(output_graph_def.node))

if __name__ == '__main__':
    # 训练时候检查点文件路径
    input_checkpoint = 'D:/mnist/logs/conv_10000steps_log/checkpoint.ckpt'
    # 即将保存到模型文件全路径
    output_graph = "D:/mnist/modelfiles/conv_10000steps_frozen_model.pb"
    freeze_graph(input_checkpoint, output_graph)

运行后会在我们设置的路径下看到.pb文件,他就是我们保存的模型文件。

(5) 调用保存的模型进行识别

# -*- coding:utf-8 -*-  
import argparse
import cv2
import numpy as np
import tensorflow as tf

# 定义加载图的函数
def load_graph(frozen_graph_filename):  
    with tf.gfile.GFile(frozen_graph_filename, "rb") as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    # We load the graph_def in the default graph  
    with tf.Graph().as_default() as graph:
        tf.import_graph_def(
            graph_def,
            input_map=None,
            return_elements=None,
            name="prefix",  # 可以理解为“图”的名字
            op_dict=None,
            producer_op_list=None
        )
    return graph


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--frozen_model_filename", default="D:/mnist/modelfiles/conv_10000steps_frozen_model.pb",
                        type=str, help="Frozen model file to import")
    args = parser.parse_args()
    # 加载已经将参数固化后的图  
    graph = load_graph(args.frozen_model_filename)

    # We can list operations  
    # op.values() gives you a list of tensors it produces  
    # op.name gives you the name  
    # 输入,输出结点也是operation,所以,我们可以得到operation的名字  
    for op in graph.get_operations():
        print(op.name, op.values())

    # 为了预测,我们需要找到我们需要feed的tensor,那么就需要该tensor的名字  
    # 注意prefix/Img_Label_Input/image_input仅仅是操作的名字,prefix/Img_Label_Input/image_input:0才是tensor的名字  

    # input placeholder
    x = graph.get_tensor_by_name('prefix/Img_Label_Input/image_input:0')
    y_ = graph.get_tensor_by_name('prefix/Img_Label_Input/label_input:0')
    keep_prob = graph.get_tensor_by_name('prefix/Fully_Connnected_Layer1/keep_prob:0')

    # output
    res_prob = graph.get_tensor_by_name('prefix/Fully_Connnected_Layer2/class_prob:0')
    res_class = tf.argmax(res_prob, 1)
    accuracy = graph.get_tensor_by_name('prefix/Training/accuracy:0')

    # 打开会话启动图
    with tf.Session(graph=graph) as sess:
        # 以预处理的出片作为输入,进行测试
        img = cv2.imread("D:/dev_sw/picVideo/digits/mydigits/dgs/9.jpg", 0)
        arr1 = np.reshape((img.astype(np.float32) / 255.0), (1, 784))

        prob, num = sess.run([res_prob, res_class], feed_dict={x: arr1, keep_prob: 1.0})

        print("Result:", prob)
        print("Class:", num)

        # 用mnsit测试集测试模型准确率
        from tensorflow.examples.tutorials.mnist import input_data
        mnist_data_dir = "path/to/mnist_data"
        mnist = input_data.read_data_sets(mnist_data_dir, one_hot=True)
        test_accuracy = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})
        print('test accuracy:%g' % test_accuracy)


您可能感兴趣的与本文相关的镜像

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值