TensorFlow学习记录

本文仅做学习记录之用
TensorFlow官网链接。感觉写的很全面,打算按照这个学下去,后续的记录暂定按照它的目录来。

新手入门

1.1介绍

这段代码应该是最基本的了,比较少,不会的点就直接查,但是涉及tensorflow的会在后面逐渐记录
np.float32()是令内部元素的类型为float32
np.random.rand()返回一组元素在[0,1)之间均匀分布的随机样本,如:

import numpy as np
print(np.random.rand(2,3)) # (2,3)表示维度

"""
输出:
[[ 0.77683057  0.13237516  0.50873495]
 [ 0.39650787  0.52095996  0.05808078]]
"""

与之类似的,np.random.random()的返回值同上,但输入参数不同,np.random.random()的参数是tuple,而np.random.rand()接受的是离散的参数,即np.random.random((2,3)) == np.random.rand(2,3)
还有,np.random.randn()返回一个或一组服从标准正态分布(即N(0, 1))的随机样本值。

import numpy as np
print(np.random.randn(2,3)) # (2,3)表示维度

"""
输出:
[[ 0.46352983  0.01918194 -0.60883008]
 [ 0.06863566  2.55242719  0.74146498]]
"""

np.dot()表示矩阵相乘。如矩阵AB相乘可以是np.dot(A, B)A.dot(B)。官网说A @ B也可以,自己跑的时候不知道为什么报错。

A = np.array( [[1,1], [0,1]] )
B = np.array( [[2,0], [3,4]] )

print("np.dot(A, B): ", np.dot(A, B))
print("A.dot(B): ", A.dot(B))

'''
输出
np.dot(A, B):  array([[5, 4], [3, 4]])
A.dot(B):  array([[5, 4], [3, 4]])
'''

xrange()range()的区别:
这两者基本一致,区别在于range()返回一个list,而xrange()返回一个生成器对象。

print(range(5))
print(xrange(5))
print(list(xrange(5)))

'''
输出
[0, 1, 2, 3, 4]
xrange(5)
[0, 1, 2, 3, 4]
'''

相对而言,xrange()性能更优,不需要一上来就开辟一个内存空间,在用作for循环使用时,两者的是一致,所以直接使用xrange()

1.2 下载及安装

这个有很多博客记录,安装Anaconda再安装即可,这里不再赘述。

1.3 基本用法

TensorFlow的基本概念
1.使用图 (graph) 来表示计算任务,图中的节点被称之为 op(operation 的缩写),一个 op获得 0 个或多个 Tensor, 执行计算, 产生 0 个或多个 Tensor
2.在被称之为 会话 (Session) 的上下文 (context) 中执行图.
3.使用 tensor表示数据.
4.通过 变量 (Variable) 维护状态.
5.使用 feedfetch可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据.

TensorFlow程序的运行过程:
TensorFlow 程序通常被组织成一个构建阶段和一个执行阶段. 在构建阶段, op的执行步骤被描述成一个图. 在执行阶段, 使用会话执行执行图中的 op.
例如, 通常在构建阶段创建一个图来表示和训练神经网络, 然后在执行阶段反复执行图中的训练 op

构建阶段
构建图的第一步, 是创建源op(source op). 源op不需要任何输入, 例如 常量 (Constant). 源op的输出被传递给其它 op做运算。例如:

import tensorflow as tf

# 创建一个常量 op, 产生一个 1x2 矩阵. 这个 op 被作为一个节点
# 加到默认图中.
# 构造器的返回值代表该常量 op 的返回值.
matrix1 = tf.constant([[3., 3.]])

# 创建另外一个常量 op, 产生一个 2x1 矩阵.
matrix2 = tf.constant([[2.],[2.]])

# 创建一个矩阵乘法 matmul op , 把 'matrix1' 和 'matrix2' 作为输入.
# 返回值 'product' 代表矩阵乘法的结果.
product = tf.matmul(matrix1, matrix2)

执行阶段
构建阶段完成后,才能启动图。首先创建一个Session对象,若无参数,则为默认图。其run()函数用来执行op,如:

# 启动默认图.
sess = tf.Session()

result = sess.run(product)
print(result)

# 任务完成, 关闭会话.
sess.close()

其中,函数调用 ‘run(product)’ 触发了图中三个 op(两个常量 op和一个矩阵乘法 op) 的执行。且op通常是并发执行的。

为了避免忘记用close()释放资源,可以用with自动完成关闭动作。如:

with tf.Session() as sess:
  result = sess.run([product])
  print(result)

关于feedfetch,暂不记录。

完整教程

2.1 总揽

这节就是个链接。。。

2.2 MNIST 数据下载

按照说的下载就完事了

2.3 MNIST入门

这部分直接上代码,整理在一起后又加了些备注
这里只使用基本的机器学习方法,不考虑像素之间的邻接关系,最后加个softmax就输出结果了。

import tensorflow as tf
import input_data

# 首先下载数据,然后转换数据格式,将图像拉成一维数据,训练集和测试集都放在mnist中
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# placeholder是占为符,None表示任意维数,即不限制训练集等的数量
x = tf.placeholder("float", [None, 784])
y_ = tf.placeholder("float", [None,10])

# 用变量存储参数(权重和偏移),初始值设为0
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

# 模型。即在w·x+b后加一个softmax,作为预测值
y = tf.nn.softmax(tf.matmul(x,W) + b)

# y_是真值数据,此处是ont_hot形式,如[0,0,0,0,0,0,1,0,0,0]表示“6”,y是预测值,也是ont_hot形式
# tf.log()是对y中的每一个元素求log
# tf.reduce_sum()是计算所有元素的总和
# 最终结果cross_entropy即是交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

# GradientDescentOptimizer(0.01)表示使用梯度下降算法,学习率为0.01,也可以使用其他算法
# 目标是最小化交叉熵(cross_entropy)
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

# 再运行前,应初始化创建的变量
init = tf.global_variables_initializer()

# 启动Session,并初始化变量
sess = tf.Session()
sess.run(init)

# 迭代优化
for i in range(1000):
    # 随机抓去训练集中的100条数据
    batch_xs, batch_ys = mnist.train.next_batch(100)
    # train_step之前的op中包含占位符,需要使用feed_dict给出每一个占位符所用的值
    # 用占位符的优势在于,即使迭代几百万次,也只需要构建一个op,不同于使用常量就需要几百万个op
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
    
# 在测试集上统计准确率
# tf.argmax(y, 1)是返回y中最大值的索引,如果y是一个矩阵,则返回一组索引,对应着每行最大值的位置
# tf.equal(v1, v2)返回v1和v2对应元素是否相等,如v1 = [1,0,0] v2 = [1,1,0],则返回[ True False  True]
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

# tf.cast()是转变tensor类型,此处是将bool类型转为float
# tf.reduce_mean()是对tensor求均值
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

print("正确率:", sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
2.4 MNIST进阶

同样通过代码+注释的方法记录
这里不在使用最基本的机器学习方法,而是加入了卷积的概念。
关于卷积核,查明白了一些定义,每个卷积核有长、宽、深三个长度单位,深也就是输入通道数。

"""
MNIST进阶
"""
import tensorflow as tf
import input_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder("float", [None, 784])
y_ = tf.placeholder("float", [None,10])

# InteractiveSession类可以在运行图时插入一些计算图,相当于不再要求“构建->计算”这个顺序了
sess = tf.InteractiveSession()

# 后面的激活函数使用ReLU
# tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差。与一般的正态分布区别在于,
# truncated_normal产生大于两倍的标准差时,会重新生成数据,所以所有的元素都在两倍标准差以内。
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)

# 构建卷积函数
# tf.nn.conv2d()是卷积函数,x是输入的原图,x = [batch,in_height,in_width,in_channels],
# batch为训练过程中每迭代一次迭代的照片数,in_height,in_width分别为图片的高和宽,in_channels为图片的通道数
# W是卷积核,W = [filter_height,filter_width,in_channels,out_channels],分别为权重的高、宽、输入通道数和输出的通道数
# strides = [a,b,c,d],a、d固定为1,b、c分别是水平和垂直的滑动距离
# padding参数有两种模式:'SAME'和'VALID','SAME'模式在卷积的过程中会在原图的边缘“补0”,以匹配上卷积核,但'VALID'模式不会,
# 卷积过程中遇到无法匹配卷积核的情况,会直接舍弃那部分元素。
def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

# 构建池化函数
# 池化有三种,分别是:
# 1.mean-pooling,即对邻域内特征点只求平均,对背景保留更好;
# 2.max-pooling,即对邻域内特征点取最大,对纹理提取更好;
# 3.Stochastic-pooling,介于两者之间,通过对像素点按照数值大小赋予概率,再按照概率进行亚采样
# tf.nn.max_pool()是在原特征基础上,做最大池化,x是输入的特征,与卷积相同:x = [batch, height, width, channels]
# ksize:池化窗口的大小,因为我们不想在batch和channels上做池化,所以一般是一般是[1, height, width, 1]
# strides:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
# padding:和卷积类似,可以取'VALID' 或者'SAME',用来决定是否‘补0’
def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

# 将原本被拉成一条直线的图像,重新被转为28*28的图像,-1表示不需指定这一维的大小,会自动计算(这里是样本量),1为通道数,RGB图像为3
x_image = tf.reshape(x, [-1,28,28,1])

# 构建第一层卷积,W_conv1是第一个卷积核,b_conv1是第一个偏移
# [5, 5, 1, 32]表示卷积核为5*5,输入通道为1,输出的特征为32个
# 故而偏移量的也是32个
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

# 把x_image和权值向量进行卷积,加上偏置项,然后应用ReLU激活函数,就是让负数变为0
# 再对特征进行最大池化,feature map变为14*14*32
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

# 构建第二层卷积,W_conv1是第二个卷积核,b_conv1是第二个偏移
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

# 同上,卷积->激活->池化
# feature map变为7*7*64
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

# 构建全连接层,将feature map转为一个1024维的特征
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

# tf.nn.dropout()放在输出层之前,用于减少过拟合,同时还会自动处理神经元输出值的scale
# 参数说明 tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None,name=None) 
# x: 表示输入   keep_prob: 表示每个神经元输出不被屏蔽的概率
# 它能以不变的概率屏蔽神经元的输出,在某一次迭代中,某些权重就不会更新(当然,下一次迭代可能就更新了)
# 用占位符表示这个概率,训练时给一个0~1的概率,减少过拟合;测试时,给概率值为1,意味着不会屏蔽任何神经元的输出。
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# 输出层,从1024维特征转为10维的输出
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

# 同上,跟之前softmax一样
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

# 同上,还是使用交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))

# 使用更复杂的ADAM优化器来做梯度最速下降
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# 同上,计算准确率
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

# 变量初始化
sess.run(tf.initialize_all_variables())

# 循环迭代参数
for i in range(20000):
    batch = mnist.train.next_batch(50)
    if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
        print "step %d, training accuracy %g"%(i, train_accuracy)
    
    # 直接用train_step.run(),而不是sess.run(train_step),是不是两种都可以?
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
#     sess.run(train_step, feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

# 测试集准确率
print "test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值