赞
踩
这是黑马程序员3天带你玩转Python深度学习TensorFlow框架学习笔记
视频链接:黑马程序员3天带你玩转Python深度学习TensorFlow框架
学习目标:知道深度学习与机器学习的区别
区别:深度学习没有特征提取
特征方面
深度学习算法试图从数据中学习高级功能,这是深度学习的一个非常独特的部分。因此,减少了为每个问题开发新特征提取器的任务。适合用在难提取特征的图像、语音、自然语言处理领域
数据量和计算性能要求
机器学习需要的执行时间远少于深度学习,深度学习参数往往很庞大,需要通过大量数据的多次优化来训练参数
算法代表
常见深度学习框架对比
Tensorflow的安装
官网:https://www.tensorflow.org/
CPU版本
2 GPU版本:核芯数量多,更适合处理并行任务
pip install tensorflow==1.8 -i https://pypi.douban.com/simple
#对于 1.15 及更早版本,CPU 和 GPU 软件包是分开的:
pip install tensorflow==1.15 # CPU
pip install tensorflow-gpu==1.15 # GPU
CPU:核芯的数量少;
每一个核芯的速度更快,性能更强;更适用于处理连续性(sequential)任务。
GPU:核芯的数量多;
但是每一个核芯的处理速度较慢;更适用于并行(parallel)任务。
Tensorflow特点
官网:https://www.tensorflow.org/
TensorFlow程序通常被组织成一个构件图阶段和一个执行图阶段。
import tensorflow as tf import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 去警告 def tensorflow_demo1(): """ tensoflow的基本结构 """ # python版本 a=2 b=3 c=a+b print('python版本的加法操作:\n',c) # tensorflow实现加法操作 a_t=tf.constant(2) # 定义常量 b_t=tf.constant(3) c_t=a_t+b_t print('tensorflow版本的加法操作:\n',c_t) # 开启会话 with tf.Session() as sess: c_t_value=sess.run(c_t) print('开启会话的结果\n',c_t_value) if __name__ == '__main__': tensorflow_demo1() ''' python版本的加法操作: 5 tensorflow版本的加法操作: Tensor("add:0", shape=(), dtype=int32) 开启会话的结果 5 '''
图包含了一组tf.Operation代表的计算单元对象和tf.Tensor代表的计算单元之间流动的数据
一个图一个命名空间,互不干扰影响
通常tensorflow会默认帮我们创建一张图
查看默认图的两种方法:
def graph_demo(): # tensorflow实现加法操作 a_t = tf.constant(2) # 定义常量 b_t = tf.constant(3) c_t = a_t + b_t #查看默认图 #方法1:调用方法 defalut_g=tf.get_default_graph() print('默认图:',defalut_g) #方法2:调用属性 print('a_t的图属性: ',a_t.graph) print('c_t的图属性: ',c_t.graph) # 开启会话 with tf.Session() as sess: c_t_value = sess.run(c_t) print('sess的图属性:',sess.graph) if __name__ == '__main__': graph_demo() ''' 默认图: <tensorflow.python.framework.ops.Graph object at 0x0000026249C36E48> a_t的图属性: <tensorflow.python.framework.ops.Graph object at 0x0000026249C36E48> c_t的图属性: <tensorflow.python.framework.ops.Graph object at 0x0000026249C36E48> sess的图属性: <tensorflow.python.framework.ops.Graph object at 0x0000026249C36E48> '''
自定义图
def create_graph(): # 自定义图 new_graph=tf.Graph() # 图上下文管理器定义数据和操作 with new_graph.as_default(): a_new = tf.constant(20) b_new = tf.constant(30) c_new = a_new + b_new print("c_new:", c_new) print("a_new的图属性:", a_new.graph) print("c_new的图属性:", c_new.graph) #开启会话,执行图,注意这里需要传入自定义图对象graph with tf.Session(graph = new_graph) as sess: c_new_value=sess.run(c_new) print('自定义图的运算结果:',c_new_value) print('sess的图属性:',sess.graph) if __name__ == '__main__': create_graph() ''' c_new: Tensor("add:0", shape=(), dtype=int32) a_new的图属性: <tensorflow.python.framework.ops.Graph object at 0x000001D3439BF278> c_new的图属性: <tensorflow.python.framework.ops.Graph object at 0x000001D3439BF278> 自定义图的运算结果: 50 sess的图属性: <tensorflow.python.framework.ops.Graph object at 0x000001D3439BF278> '''
TensorBoard可视化工具
tensorflow可用于训练大规模深度神经网络所需的计算,使用该工具设计的计算往往复杂而深奥。为了更方便tensorflow程序的理解、调试与优化,tensorflow提供了TensorBoard可视化工具
实现程序可视化过程:
1、将图进行数据序列化,为events文件
TensorBoard通过读取TensorFlow的事件文件来运行,故需要将图序列化为Summary对象
tf.summary.FileWriter(path, graph=sess.graph)
2、打开终端,启动tensorBoard
tensorboard --logdir=path
def graph_demo(): # tensorflow实现加法操作 a_t = tf.constant(2) # 定义常量 b_t = tf.constant(3) c_t = a_t + b_t # 开启会话 with tf.Session() as sess: c_t_value = sess.run(c_t) print('sess的图属性:',sess.graph) # sess图序列化为summary对象 # 参数一:输出sumary对象的路径,参数二:需要进行序列化的图 tf.summary.FileWriter('./temp/summary',graph = sess.graph) if __name__ == '__main__': graph_demo()
在终端输入,注意路径
tensorboard --logdir=‘./machine_learning/temp/summary’
点击http://MSI:6006 跳到tensorBoard页面
OP 操作对象 operation
类型 | 实例 |
---|---|
标量运算 | add,sub, mul, div,exp, log, greater, less,equal |
向量运算 | concat,slice,splot, constant,rank,shape, shuffle |
矩阵运算 | matmul, matrixinverse,matrixdateminant |
带状态的运算 | Variable, assgin, assginadd |
神经网络组件 | softmax,sigmoid,relu,convolution,max_pool |
存储,恢复 | Save,Restroe |
队列及同步运算 | Enqueue,Dequeue,MutexAcquire,MutexRelease |
控制流 | Merge,Switch, Enter,Leave,Nextlteration |
操作函数 | 操作对象 |
---|---|
tf.constant(Tensor对象) | 输入Tensor对象-Const输出 Tensor对象 |
tf.add(Tensor对象1,Tensor对象2) | 输入(Tensor对象1,Tensor对象2) ,add对象,输出 Tensor对象3 |
一个b操作对象(Operation)是TensorFlow图中的一个节点,可以接收0个或者多个输入Tensor对象,并且可以输出0个或者多个Tensor,Operation对象是通过op构造函数(如tf.matmul())创建的。
例如: c = tf.matmul(a, b)创建了一个Operation对象,类型为 MatMul类型,它将张量a, b作为输入,c作为输出,,并且输出数据,打印的时候也是打印的数据。其中tf.matmul)是函数,在执行matmul函数的过程中会通过MatMul类创建—个与之对应的对象
注意,打印出来的是张量值,可以理解成OP当中包含了这个值。并且每一个OP指令都对应一个唯一的名称,如上面的Const:0,这个在TensorBoard上面也可以显示
请注意,tf.Tensor对象以输出该张量的tf.Operation明确命名。张量名称的形式为“<OP_NAME>:< i >",其中:
. "<OP_NAME>"是生成该张量的指令的名称
. "< i >"是一个整数,它表示该张量在指令的输出中的索引
指令名称
一张图有对应自己的命名空间
tf.Graph对象为其包含的 tf.Operation对象定义的一个命名空间。TensorFlow 会自动为图中的每个指令选择一个唯一名称,用户也可以指定描述性名称,使程序阅读起来更轻松。我们可以以以下方式改写指令名称
例如,tf.constant(42.0, name=“answer”)创建了一个名为“answer"的新tf.Operation并返回一个名为“answer:0”的tf.Tensor。如果默认图已包含名为"answer"的指令,则TensorFlow 会在名称上附加“1"、“2”等字符,以便让名称具有唯一性。
会话创建
1 TensorFlow使用tf.Session类来表示客户端程序(通常为Python程序,但也提供了使用其他语言的类似接口)与C++运行时之间的连接
2 tf.Session对象使用分布式TensorFlow运行时提供对本地计算机中的设备和远程设备的访问权限。
快速查看张量的值,在会话中调用 对象.eval() 查看
会话上下文管理器
会话可能拥有的资源,如tf.Variable,tf.QueueBase和tf.ReaderBase。当这些资源不再需要时,释放这些资源非常重要。因此,需要调用tf.Session.close会话中的方法,或将会话用作上下文管理器。
tf.Session(target=‘’,graph=None,config=None)
# 开启会话上下文管理器(推荐)
with tf.Session() as sess:
sess.run(sth)
# 传统的会话定义
sess=tf.Session()
sum_t=sess.run(c_t)
sess.close()
# 运行会话并打印设备信息
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True))
会话run()
run(fetches, feed_dict=None, options=None, run_metadata=None)
注: 使用tf.operation.eval()也可以运行operation,但需要在会话中运行
# 创建图
a = tf.constant(5.0)
b = tf.constant(6.0)
c = a + b
# 创建会话
sess = tf.Session()
# 计算C的值
print(sess.run(c))
print(c.eval(session=sess))
feed_dict()操作
请注意运行时候报的错误error:
RuntimeError:如果这Session是无效状态(例如已关闭)。
TypeError:如果fetches或者feed_dict键的类型不合适。
valueError:如果fetches或feed_dict键无效或引用Tensor不存在的键。
def feed_dict_demo(): # 当不确定值的时候,通过placeholder占位符解决 a=tf.placeholder(tf.float32) b=tf.placeholder(tf.float32) c=tf.add(a,b) #开启会话,打印设备 with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)) as sess: c_value=sess.run([a,b,c],feed_dict={a:3.2,b:2.3}) print('c_value: ',c_value) if __name__ == '__main__': feed_dict_demo() ''' Device mapping: no known devices. Add: (Add): /job:localhost/replica:0/task:0/device:CPU:0 Placeholder_1: (Placeholder): /job:localhost/replica:0/task:0/device:CPU:0 Placeholder: (Placeholder): /job:localhost/replica:0/task:0/device:CPU:0 c_value: [array(3.2, dtype=float32), array(2.3, dtype=float32), 5.5] '''
TensorFlow的张量就是一个N维数组,类型为tf.Tensor。
标量:一个数字----0阶张量
向量:一维数组-----1阶张量
矩阵:二维数组------2阶张量
3阶张量
张量的类型
数据类型 | Python类型 | 描述 |
---|---|---|
DT_FLOAT | tf.float32 | 32位浮点数. |
DT_DOUBLE | tf.float64 | 64位浮点数. |
DT_INT64 | tf. int64 | 64位有符号整型. |
DT_INT32 | tf. int32 | 32位有符号整型. |
DT_INT16 | tf.int16 | 16位有符号整型. |
DT_INT8 | tf.int8 | 8位有符号整型. |
DT_UINT8 | tf.uint8 | 8位无符号整型. |
DT_STRING | tf.string | 可变长度的字节数组.每一个张量元素都是一个字节数组. |
DT_BOOL | tf.bool | 布尔型. |
DT_COMPLEX64 | tf.complex64 | 由两个32位浮点数组成的复数:实数和虚数. |
DT_QINT32 | tf.qint32 | 用于量化Ops的32位有符号整型. |
DT_QINT8 | tf.qint8 | 用于量化Ops的8位有符号整型. |
DT_QUINT8 | tf.quint8 | 用于最化Ops的8位无符号整型 |
张量的阶
阶 | 数学实例 | Python | 例子 |
---|---|---|---|
0 | 表量 | (只有大小) | s = 483 |
1 | 向量 | (大小和方向) | v = [1.1,2.2,3.3] |
2 | 矩阵 | (数据表) | m = [[1,2,3],[4,5.6],[7,8,9]] |
3 | 3阶张量 | (数据立体) | t = [[[2],[4],[6]],[[8],[10],[12]],[[14],[16],[18]]] |
n | n阶 | (自己想想看) |
def tensor_demo(): """ 张量的演示 """ tensor1 = tf.constant(4.0) tensor2 = tf.constant([1,2,3,4]) # 未指定类型,默认类型 linear_squares = tf.constant([[4],[9],[16],[25]],dtype=tf.int32) print("tensor1:", tensor1) print("tensor2:", tensor2) print("linear_square:", linear_squares) return None if __name__ == "__main__": tensor_demo() ''' tensor1: Tensor("Const:0", shape=(), dtype=float32) tensor2: Tensor("Const_1:0", shape=(4,), dtype=int32) linear_square: Tensor("Const_2:0", shape=(4, 1), dtype=int32) '''
创建固定值张量
tf.zeros(shape, dtype=tf.float32,name=None)
创建所有元素设置为零的张量。此操作返回一个dtype具有形状shape和所有元素设置为零的类型的张量。
tf.zeros_like(tensor,dtype=None, name=None)
给tensor定单张量(),此操作返回tensor与所有元素设置为零相同的类型和形状的张量。
tf.ones(shape, dtype=tf.float32, name=None)
创建一个所有元素设置为1的张量。此操作返回一个类型的张量,dtype形状shape和所有元素设置为1。
tf.ones_like(tensor, dtype=None, name=None)
给tensor定单张量(),此操作返回tensor与所有元素设置为1相同的类型和形状的张量。
tf.fill(dims, value, name=None)
创建一个填充了标量值的张量。此操作创建一个张量的形状dims并填充它value.
tf.constant(value, dtype=None,shape=None, name=‘Const’"
创建一个常数张量。
创建随机张量
一般我们经常使用的随机数函数Math.randoml()产生的是服从均匀分布的随机数,能够模拟等概率出现的情况,例如扔一个骰子,1到6点的概率应该相等,但现实生活中更多的随机现象是符合正态分布的,例如20岁成年人的体重分布等。
假如我们在制作一个游戏,要随机设定许许多多NPC的身高,如果还用Math.random),生成从140到220之间的数字,就会发现每个身高段的人数是一样多的,这是比较无趣的,这样的世界也与我们习惯不同,现实应该是特别高和特别矮的都很少,处于中间的人数最多,这就要求随机函数符合正态分布。
tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32,seed=None,name=None)
从截断的正态分布中输出随机值,和 tf.random_normal(0一样,但是所有数字都不超过两个标准差
tf.random_normal(shape, mean=0.0,stddev=1.0, dtype=tf.float32, seed=None, name=None)
从正态分布中输出随机值,由随机正态分布的数字组成的矩阵
其它特殊的创建张量的OP
tf.Variable
tf.placeholder
1 类型改变
def cast_demo():
a=tf.constant(4.0)
b=tf.cast(a,dtype = tf.float64)
print(a)
print(b)
if __name__ == '__main__':
cast_demo()
'''
Tensor("Const:0", shape=(), dtype=float32)
Tensor("Cast:0", shape=(), dtype=float64)
'''
2 形状改变
tensorflow的张量具有两种形状变换,动态形状和静态形状
静态形状:初始创建张量时的形状
什么情况下可以改变静态形状:
只有在形状还没有完全固定下来的情况下,如shape(?,?);转换形状的时候,只能一维到一维,二维到二维,而不能跨维度改变形状,如 shape=[None, 10],前面无所谓变化,但后面一个必须要10
def shape_demo(): a = tf.constant(4.0) b = tf.placeholder(dtype=tf.float32, shape=[None, 10]) print('a:',a) print('b:',b) b.set_shape((2,10)) print('修改b静态形状',b) c_dynamic=tf.reshape(b,shape = (10,2)) # c_dynamic=tf.reshape(b,shape = (10,10)) 报错 print('修改b动态形状',c_dynamic) if __name__ == '__main__': shape_demo() ''' a: Tensor("Const:0", shape=(), dtype=float32) b: Tensor("Placeholder:0", shape=(?, 10), dtype=float32) 修改b静态形状 Tensor("Placeholder:0", shape=(2, 10), dtype=float32) 修改b动态形状 Tensor("Reshape:0", shape=(10, 2), dtype=float32) '''
张量的数学运算,自己去查api
TensorFlow变量是表示程序处理的共享持久状态的最佳方法。变量通过tf.Variable类进行操作。
变量的特点:
tf.Variable(initia_value=None, trainable=True, collections=None, name=None)
注意:创建完变量后,需要进行变量初始化,且运行该初始化后,才能使用变量
init = tf.global_variables_initializer()
sess.run(init)
def variable_demo(): #创建变量 a=tf.Variable(initial_value = 30) b=tf.Variable(initial_value = 50) c=tf.add(a,b) print('a:',a) print('b:',b) print('c:',c) # 变量初始化 init=tf.global_variables_initializer() #开启会话 with tf.Session() as sess: sess.run(init) # 运行初始化 a_value,b_value,c_value=sess.run([a,b,c]) print('a_value,',a_value) print('b_value,',b_value) print('c_value,',c_value) if __name__ == '__main__': variable_demo() ''' a: <tf.Variable 'Variable:0' shape=() dtype=int32_ref> b: <tf.Variable 'Variable_1:0' shape=() dtype=int32_ref> c: Tensor("Add:0", shape=(), dtype=int32) a_value, 30 b_value, 50 c_value, 80 '''
tf.variable_scope()
def scope_demo(): with tf.variable_scope('myscore'): a = tf.Variable(initial_value = 30) b = tf.Variable(initial_value = 50) with tf.variable_scope('yourscore'): c = tf.add(a, b) print('a:', a) print('b:', b) print('c:', c) if __name__ == '__main__': scope_demo() ''' a: <tf.Variable 'myscore/Variable:0' shape=() dtype=int32_ref> b: <tf.Variable 'myscore/Variable_1:0' shape=() dtype=int32_ref> c: Tensor("yourscore/Add:0", shape=(), dtype=int32) '''
1、tf.app
这个模块相当于为TensorFlow进行的脚本提供一个main函数入口,可以定义脚本运行的flags
2、tf.image
TensorFlow的图像处理操作。主要是一些颜色变换、变形和图像的编码和解码
3、tf.gfile
这个模块提供了一组文件操作函数
4、tf.summary
用来生成TensorBoard可用的统计日志,目前Summary主要提供了4种类型:
audio、image、histogram、scalar
5、tf.python_io
用来读写TFRecords文件
6、tf.train
这个模块提供了一些训练器,与tf.nn结合起来,实现一些网络的优化计算
7、tf.nn
这个模块提供了一些构建神经网络的底层函数。TensorFlow构建网络的核心模块,其中包含了添加各种层的函数,比如添加卷积层、池化层等。
1、tf.keras
Kears本来是一个独立的深度学习库,tensorflow将其学习过来,增加这部分模块在于快速构建模型
2、tf.layers
高级API,以便高级的概念层来定义一个模型。类似tf.kears
3、tf.contrib
tf.contrib.layers提供够将计算图中的网络层、正则化、摘要操作,是构建计算图的高级操作,但是tf.contrib包含不稳定和实验代码,有可能以后API会改变
4、tf.estimator
一个estimator相当于model + training + evaluate 的合体。在模块中,已经实现了几种简单的分类器和回归其,包括:Baseline,learning 和 DNN。这里的DNN的网络,只是全连接网络,没有提供卷积之类的
关于tensorflow的API展示
回顾:根据数据建立回归模型,w1x1+w2x2+…+b = y,通过真实值与预测值之间建立误差,使用梯度下降优化得到损失最小对应的权重和偏置。最终确定模型的权重和偏置参数。最后可以用这些参数进行预测。
使用到的API
运算:
梯度下降优化:
tf.train.GradientDescentOptimizer(learning_rate)
梯度下降优化
learning_rate:学习率,一般为0~1之间比较小的值
method:
return:梯度下降op
分析
1)准备真实数据:
tf.random_normal()
x:特征值,形状:(100,1),随机指定100个点,只有一个特征值
y_true:目标值,形状:(100,1)
y_true = 0.8x + 0.7 ,100个样本
即假设x和y之间的关系满足: y =kx + b, 最后求出k≈0.8,b=0.7 为正确的答案
即y_predict=x*weights+bias
2)构建模型
y_predict = tf.matmul(x, weights) + bias
3)构造损失函数(均方误差)
error = tf.reduce_mean(tf.square(y_predict - y_true))
4)优化损失:梯度下降优化器
optimizer = tf.train.GrandientDescentOptimizer(learning_rate=0.01).minimize(error)
def linear_regression(): # 1、准备数据 X=tf.random_normal(shape=[100,1]) # 特征值 100行1列 y_true=tf.matmul(X,[[0.8]])+0.7 # 真实值 y_true = 0.8x + 0.7 # 2、构建模型 # 采用变量定义模型参数 weigths=tf.Variable(initial_value = tf.random_normal(shape = [1,1])) # 权重 bias=tf.Variable(initial_value = tf.random_normal(shape = [1,1])) # 偏置 y_predict=tf.matmul(X,weigths)+bias # 预测值 # 3、构建损失函数(均方误差) error=tf.reduce_mean(tf.square(y_predict-y_true)) # 4、优化损失函数 optimizer=tf.train.GradientDescentOptimizer(learning_rate = 0.01).minimize(error) # 初始化变量 init=tf.global_variables_initializer() # 开启会话 with tf.Session() as sess: sess.run(init) # 运行初始化 # 查看没有训练之前,初始化模型参数值 print('训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(weigths.eval(),bias.eval(),error.eval())) # 开始训练模型,迭代100次 for i in range(100): sess.run(optimizer) print('第%d次训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(i+1,weigths.eval(),bias.eval(),error.eval())) if __name__ == '__main__': linear_regression() ''' 训练前模型参数为:权重-2.152965, 偏置-1.636178, 损失值14.106889 第1次训练前模型参数为:权重-2.086562, 偏置-1.589710, 损失值15.449847 第2次训练前模型参数为:权重-2.022885, 偏置-1.536769, 损失值12.712150 第3次训练前模型参数为:权重-1.953819, 偏置-1.488234, 损失值11.221785 ..... 第98次训练前模型参数为:权重0.379509, 偏置0.383643, 损失值0.302479 第99次训练前模型参数为:权重0.386806, 偏置0.389533, 损失值0.247333 第100次训练前模型参数为:权重0.396212, 偏置0.395469, 损失值0.296869 '''
学习率的设置、步数的设置与梯度爆炸
学习率越大,训练到较好结果的步数越小;学习率越小,训练到较好结果的步数越大。
但是学习过大会出现梯度爆炸现象。
如何解决梯度爆炸问题(深度神经网络当中更容易出现)
目的:在TensorBoard当中观察模型的参数、损失值等变量值的变化
1、收集变量
2、合并变量写入事件文件
创建事件文件 tf.summary.FileWriter('path, graph=sess.graph)
merged = tf.summary.merge_all() 合并变量
运行合并: summary = sess.run(merged),每次迭代都需运行
添加:FileWriter.add_summary(summary,i),i表示第几次的值
def linear_regression(): # 1、准备数据 X=tf.random_normal(shape=[100,1]) # 特征值 100行1列 y_true=tf.matmul(X,[[0.8]])+0.7 # 真实值 y_true = 0.8x + 0.7 # 2、构建模型 # 采用变量定义模型参数 weigths=tf.Variable(initial_value = tf.random_normal(shape = [1,1])) # 权重 bias=tf.Variable(initial_value = tf.random_normal(shape = [1,1])) # 偏置 y_predict=tf.matmul(X,weigths)+bias # 预测值 # 3、构建损失函数(均方误差) error=tf.reduce_mean(tf.square(y_predict-y_true)) # 4、优化损失函数 optimizer=tf.train.GradientDescentOptimizer(learning_rate = 0.01).minimize(error) # 初始化变量 init=tf.global_variables_initializer() # 收集变量 tf.summary.scalar('error',error) tf.summary.histogram('weights',weigths) tf.summary.histogram('bias',bias) # 合并变量 merged=tf.summary.merge_all() # 开启会话 with tf.Session() as sess: sess.run(init) # 运行初始化 # 查看没有训练之前,初始化模型参数值 print('训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(weigths.eval(),bias.eval(),error.eval())) # 创建事件文件 file_writer=tf.summary.FileWriter('./temp/linear/',graph = sess.graph) # 运行合并变量操作 summary=sess.run(merged) # 开始训练模型,迭代100次 for i in range(100): sess.run(optimizer) print('第%d次训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(i+1,weigths.eval(),bias.eval(),error.eval())) # 将每次迭代后的合并变量写入到事件文件中 file_writer.add_summary(summary,i) if __name__ == '__main__': linear_regression()
在Terminal输入 tensorboard --logdir=‘./temp/linear’
tf.variable_scope(name=‘’)
使得代码结构更加信息,TensorBoard图结构更加清楚
def linear_regression(): # 1、准备数据 with tf.variable_scope('prepare_data'): X=tf.random_normal(shape=[100,1],name='feature') # 特征值 100行1列 y_true=tf.matmul(X,[[0.8]])+0.7 # 真实值 y_true = 0.8x + 0.7 # 2、构建模型 # 采用变量定义模型参数 with tf.variable_scope('create_model'): weigths=tf.Variable(initial_value = tf.random_normal(shape = [1,1]),name = 'Weights') # 权重 bias=tf.Variable(initial_value = tf.random_normal(shape = [1,1]),name='Bias') # 偏置 y_predict=tf.matmul(X,weigths)+bias # 预测值 # 3、构建损失函数(均方误差) with tf.variable_scope('loss_function'): error=tf.reduce_mean(tf.square(y_predict-y_true)) # 4、优化损失函数 with tf.variable_scope('optimizer'): optimizer=tf.train.GradientDescentOptimizer(learning_rate = 0.01).minimize(error) # 初始化变量 init=tf.global_variables_initializer() # 收集变量 tf.summary.scalar('error',error) tf.summary.histogram('weights',weigths) tf.summary.histogram('bias',bias) # 合并变量 merged=tf.summary.merge_all() # 开启会话 with tf.Session() as sess: sess.run(init) # 运行初始化 # 查看没有训练之前,初始化模型参数值 print('训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(weigths.eval(),bias.eval(),error.eval())) # 创建事件文件 file_writer=tf.summary.FileWriter('./temp/linear/',graph = sess.graph) # 运行合并变量操作 summary=sess.run(merged) # 开始训练模型,迭代100次 for i in range(100): sess.run(optimizer) print('第%d次训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(i+1,weigths.eval(),bias.eval(),error.eval())) # 将每次迭代后的合并变量写入到事件文件中 file_writer.add_summary(summary,i) if __name__ == '__main__': linear_regression()
tf.train.Saver(var_list=None,max_to_keep=5)
步骤:
注意:
1、path,目录一定要提前创建
2、保存的是会话(里面是具体模型的参数)
3、保存模型的格式为 ckpt
def linear_regression(): # 1、准备数据 with tf.variable_scope('prepare_data'): X=tf.random_normal(shape=[100,1],name='feature') # 特征值 100行1列 y_true=tf.matmul(X,[[0.8]])+0.7 # 真实值 y_true = 0.8x + 0.7 # 2、构建模型 # 采用变量定义模型参数 with tf.variable_scope('create_model'): weigths=tf.Variable(initial_value = tf.random_normal(shape = [1,1]),name = 'Weights') # 权重 bias=tf.Variable(initial_value = tf.random_normal(shape = [1,1]),name='Bias') # 偏置 y_predict=tf.matmul(X,weigths)+bias # 预测值 # 3、构建损失函数(均方误差) with tf.variable_scope('loss_function'): error=tf.reduce_mean(tf.square(y_predict-y_true)) # 4、优化损失函数 with tf.variable_scope('optimizer'): optimizer=tf.train.GradientDescentOptimizer(learning_rate = 0.01).minimize(error) # 初始化变量 init=tf.global_variables_initializer() # 收集变量 tf.summary.scalar('error',error) tf.summary.histogram('weights',weigths) tf.summary.histogram('bias',bias) # 合并变量 merged=tf.summary.merge_all() # 开启会话 with tf.Session() as sess: sess.run(init) # 运行初始化 # 查看没有训练之前,初始化模型参数值 print('训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(weigths.eval(),bias.eval(),error.eval())) # 创建事件文件 file_writer=tf.summary.FileWriter('./temp/linear/',graph = sess.graph) # 运行合并变量操作 summary=sess.run(merged) # 实例化Saver saver=tf.train.Saver() # 开始训练模型,迭代100次 # for i in range(100): # sess.run(optimizer) # print('第%d次训练前模型参数为:权重%f, 偏置%f, 损失值%f '%(i+1,weigths.eval(),bias.eval(),error.eval())) # # # 将每次迭代后的合并变量写入到事件文件中 # file_writer.add_summary(summary,i) # 保存模型 # if i%10==0: # saver.save(sess,save_path = './temp/model/my_linear.ckpt') # 加载模型 if os.path.exists('./temp/model/checkpoint'): saver.restore(sess, './temp/model/my_linear.ckpt') print('训练后模型参数为:权重%f, 偏置%f, 损失值%f ' % (weigths.eval(), bias.eval(), error.eval())) if __name__ == '__main__': linear_regression() ''' 训练前模型参数为:权重-1.358256, 偏置2.844705, 损失值6.984871 训练后模型参数为:权重0.486487, 偏置0.413228, 损失值0.159787 '''
tf.app.flags(DEFINE),它支持应用从命令行接受参数,可以用来指定集群配置等。在tf.app.flags()下面有各种定义参数的类型
#定义一些常用的命令行参数
#训练步数
tf.app.flags.DEFINE_integer("max_step",0,"训练模型的步数")
#定义模型的路径
tf.app.flags.DEFINE_string("model_dir", " ","模型保存的路径+模型名字")
#定义获取命令行参数
FLAGS = tf.app.flags.FLAGS
tf.app.flags(DEFINE) 使用
import tensorflow as tf import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 去警告 # 1)定义命令行参数 tf.app.flags.DEFINE_integer("max_step", 100, "训练模型的步数") tf.app.flags.DEFINE_string("model_dir", "Unknown", "模型保存的路径+模型的名字") # 2)简化变量名 FLAGS = tf.app.flags.FLAGS def command_demo(): """ 命令行参数演示 """ print("max_step:", FLAGS.max_step) print("model_dir:", FLAGS.model_dir) if __name__ == '__main__': command_demo() ''' max_step: 100 model_dir: Unknown '''
tf.app.run()使用
def main(argv):
"""
这里是总文件,各种模块调用写在这里
"""
print(argv)
if __name__ == '__main__':
tf.app.run()
'''
['E:/RuanJian_2/PyCharm/PyCode/heima/junior/machine_learning/tensorflow_demo1.py']
'''
shuffle 洗牌
第一阶段:构造文件名队列
第二阶段:读取与解码
第三阶段:批处理 (需要手动开启线程)
注意:这些操作需要启动运行这些队列操作的线程,以便我们在进行文件读取的过程中能够顺利进行入队出队操作
1、构造文件名队列
将需要读取的文件的文件名放入到文件名队列
tf.train.string_input_producer(string_tensor, shuffle=True)
2、读取与解码
从队列当中读取文件内容,并进行解码操作。
2.1、读取文件内容
阅读器默认每次只读取一个样本
具体来说:
文本文件默认一次读取一行,图片文件默认一次读取一张图片,二进制文件一次读取指定字节数(最好是一个样本的字节数),TFRecords默认一次读取一个example
1、它们有共同的读取方法: read(file_queue),并且都会返回一个Tensors元组(key文件名字,value默认的内容(一个样本))
2、由于默认只会读取一个样本,所以如果想要进行批处理,需要使用tf.train.batch或tf.train.shuffle_batch进行批处理操作,便于之后指定每批次多个样本的训练。
即file_queue=tf.train.strng_input_produce(string_tensor, shuffle=True)
key,value=读取器.read(file_queue)
key: 文件名
value: 一个样本
2.2、内容解码
读取不同类型的文件,也应该对读取到的不同类型的内容进行相对应的解码操作,解码成统一的Tensor格式
解码阶段,默认所有的内容都解码成tf.uint8类型,如果之后需要转换成指定类型则可使用 tf.cast() 进行相应转换。
3 批处理
解码之后,可以直接获取默认的一个样本内容了,但如果想要获取多个样本,需要加入到新的队列进行批处理。
tf.train.batch(tensors, batch_size, num_threads = 1, capacity = 32,name=None)
读取指定大小(个数)的张量
tensors:可以是包含张量的列表,批处理的内容放到列表当中
batch_size:从队列中读取的批处理大小
num_threads:进入队列的线程数
capacity:整数,队列中元素的最大数量
return:tensors
tf.train.shuffle_batch() : 随机批量操作
以上用到的队列都是tf.train.QueueRunner对象。
每个QueueRunner都负责一个阶段,tf.train.start_queue_runners()函数会要求图中的每个QueueRunner启动它的运行队列操作的线程。(这些操作需要在会话中开启)
tf.train.start_queue_runners(sess=None, coord=None)
tf.train.Coordinator()
组成图片最基本单位是 像素
1、图片三要素
组成一张图片特征值是所有的像素值,有三个维度:图片长度、图片宽度、图片通道数
图片的通道数是什么?
描述一个像素点,如果是灰度图,那么只需要一个数值来描述它,就是单通道
如果一个像素点,有RGB三种颜色来描述它,及时三通道
灰度图:单通道,[长,宽,1]
彩色图片:三通道,[长,宽,3] 像素点为 长 X 宽 X 3
2、张量形状
在TensorFlow中如何用张量表示一张图片呢?
一张图片可以被表示成一个3D张量,即其形状为[height,width, channel],height就表示高,width表示宽,channel表示通道数。我们会经常遇到3D和4D的表示
为什么要缩放图片到统一大小?
在进行图像识别的时候,每个图片样本的特征数量要保持相同。所以需要将所有图片张量大小统一转换
缩小放大图片
tf.image**.resize_images**(images, size)
images:4-D形状[batch, height, width, channels]或3-D形状的张量[height, width, channels]的图片数据
size:1-D int32张量:new_height,new_width,图像的新尺寸
返回4-D格式或者3-D格式图片
存储:unit8(节省空间)
矩阵计算:float32(提高精度)
流程:
1)构造文件名队列
2)读取与解码,使样本的形状和类型统一
3)批处理,一次性处理多张图片
def picture_read(file_list): #1、构建文件名队列 file_queue=tf.train.string_input_producer(file_list) #2、文件读取与解码 reader=tf.WholeFileReader() # 图片的读取器 # key是文件名,value是一张图片的原始编码形式 key,value=reader.read(file_queue) # 图片的读取 print("key:", key) print("value:", value) # 解码阶段 image=tf.image.decode_jpeg(value) # 解码jepg格式 print('image:',image) # 图片形状,类型修改 image_resize=tf.image.resize_images(image,[200,200]) # 统一行列为200 print('image_resize:',image_resize) # 静态形状修改 image_resize.set_shape(shape = [200,200,3]) # 能用静态形状就用静态,不行再用动态 # 3、批处理(一次性处理多张图片) 这里1个线程处理100张图片 image_batch=tf.train.batch([image_resize],batch_size = 100,num_threads = 1,capacity = 100) print("image_batch:", image_batch) # 开启会话 with tf.Session() as sess: # 创建线程协调员 coord=tf.train.Coordinator() # 开启线程 threads=tf.train.start_queue_runners(sess=sess,coord = coord) key_new, value_new, image_new, image_resize_new, image_batch_new = sess.run([key, value, image, image_resize, image_batch]) print("key_new:", key_new) print("value_new:", value_new) print("image_new:", image_new) print("image_resize_new:", image_resize_new) print("image_batch_new:", image_batch_new) # 回收线程,如果不回收,会一直占用系统资源 coord.request_stop() # 停止线程 coord.join(threads) # 回收线程 pass if __name__ == '__main__': file_name=os.listdir('./data/image/dog') # 构造路径 + 文件名的列表 file_list=[os.path.join('./data/image/dog',file) for file in file_name] print(file_name) print(file_list) picture_read(file_list) ''' ['dog.1.jpg', 'dog.10.jpg', 'dog.100.jpg', 'dog.11.jpg', 'dog.12.jpg', 'dog.13.jpg', 'dog.14.jpg', 'dog.15.jpg', ....., 'dog.99.jpg'] ['./data/image/dog\\dog.1.jpg', './data/image/dog\\dog.10.jpg', './data/image/dog\\dog.100.jpg', './data/image/dog\\dog.11.jpg', './data/image/dog\\dog.12.jpg', './data/image/dog\\dog.13.jpg', './data/image/dog\\dog.14.jpg', './data/image/dog\\dog.15.jpg',...., './data/image/dog\\dog.99.jpg'] key: Tensor("ReaderReadV2:0", shape=(), dtype=string) value: Tensor("ReaderReadV2:1", shape=(), dtype=string) image: Tensor("DecodeJpeg:0", shape=(?, ?, ?), dtype=uint8) image_resize: Tensor("resize_images/Squeeze:0", shape=(200, 200, ?), dtype=float32) image_batch: Tensor("batch:0", shape=(100, 200, 200, 3), dtype=float32) key_new: b'./data/image/dog\\dog.50.jpg' value_new: b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\n\x07\x07\x08\x07\x06\n\x08\x08\x08\x0b\n\n\x0b\x0e\x18\x10\x0e\r\r\x0e\x1d\x15\x16\x11\x18#\x1f%$"\x1f"!&+7/&)4)!"0A149;>>>%.DIC<H7=>;\xff\xdb\x00C\x01\n\x0b\x0b\x0e\r\x0e\x1c\x10\x10\x1c;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\xff\xc0\x00\x11\x08\x00\xc7\x00\x9d\x03\x01"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01}\x01\x02\x03\x00\x04\x11\x05\x12!1A\x06\x13Qa\x07"q\x142\x81\x91\xa1\x08#B\xb1\xc1\x15R\xd1\xf0$3br\x82\t\n\x16\x17\x18\x19\x1a%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xc4\x00\x1f\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\xff\xc4\x00\xb5\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02w\x00\x01\x02\x03\x11\x04\x05!1\x06\x12AQ\x07aq\x13"2\x81\x08\x14B\x91\xa1\xb1\xc1\t#3R\xf0\x15br\xd1\n\x16$4\xe1%\xf1\x17\x18\x19\x1a&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?' image_new: [[[ 62 78 67] [ 42 58 47] [ 69 85 74] ... [193 223 225] [194 221 230] [149 172 188]] [[ 55 71 60] [ 46 62 51] [ 56 72 61] ... [231 231 231] [231 231 231] [231 231 231]]] image_resize_new: [[[ 62. 78. 67. ] [ 46.3 62.3 51.3 ] [ 57.39 73.39 62.39 ] ... [231. 231. 231. ] [231. 231. 231. ] [231. 231. 231. ]]] image_batch_new: [[[[ 0. 0. 0. ] [ 0. 0. 0. ] [ 0. 0. 0. ] ... [[125.09195 128.09195 137.09195 ] [171.11003 174.03503 183.26003 ] [129.0711 131.0711 143.2211 ] ... [ 15.224976 15.224976 15.224976 ] [ 12.149994 12.149994 12.149994 ] [ 11. 11. 11. ]]] [ 77.06506 45.09503 13.125 ] [ 74.14496 43.14496 15.1449585] [ 78.745026 47.745026 18.745026 ]]]] Process finished with exit code 0 '''
CIFAR10数据集官网: https://www.cs.toronto.edu/~kriz/cifar.html
数据集分为五个训练批次和一个测试批次,每个批次有 10000 张图像。测试批次恰好包含来自每个类别的 1000 个随机选择的图像。训练批次包含随机顺序的剩余图像,但一些训练批次可能包含来自一个类的图像多于另一个。在它们之间,训练批次恰好包含来自每个类别的 5000 张图像
二进制版本数据文件
二进制版本包含文件data_batch_1.bin,data_batch_2.bin,…,data_batch_5.bin以及test_batch.bin
cifar10 的特征值是 image(3072Bytes) 目标值是 label 0-9 (1Bytes)
这些文件中的每一个格式如下,数据中每个样本包含了特征值和目标值:
<1×标签><3072×像素>
…
<1×标签><3072×像素>
第一个字节是第一个图像的标签,它是一个0-9范围内的数字。接下来的3072个字节是图像像素的值。前1024个字节是红色通道值,下1024个绿色,最后1024个蓝色。值以行优先顺序存储,因此前32个字节是图像第一行的红色通道值。每个文件都包含10000个这样的3073字节的“行"图像,但没有任何分隔行的限制。因此每个文件应该完全是30730000字节长。
即一个样本的形式为: 1+1024r+1024g+1024b=3073个字节
流程分析
1、构建文件名队列
file_queue=tf.train.string_input_producer(file_list)
2、读取与解码
reader=tf.FixedLengthRecordReader(3073)
key,value=reader.read(file_queue)
decoded=tf.decoded_raw(value,tf.uint8)
对tensor对象进行切片 label
一个样本image(3072字节=1024r+1024g+1024b)
[[r[32,32]],[g[32,32]],[b[32,32]]] 32x32=1024
shape=(3,32,32) = (channels,height,width)
故需要转换为TensorFlow的图像表示(height,width,channels)
tf.transpose(image,[a,b,c])
如 image_new=tf.transpose(image,[1,2,0]) 参数二是将image的原来索引位置,换成现在对应的索引。
即image_new 0,1,2的位置的值,对应image 1,2,0位置的值
3、批处理
tf.train.batch(tensors, batch_size, num_threads = 1, capacity = 32,name=None)
NHWC与NCHW
在读取设置图片形状的时候有两种格式:
设置为“NHWC"时,排列顺序为 [batch, height, width,channels];
设置为“NCHW"时,排列顺序为[batch, channels, height, width]。
其中N表示这批图像有几张,H表示图像在竖直方向有多少像素,W表示水平方向像素数,C表示通道数。
Tensorflow默认的[height, width, channel]
class Cifar(object): def __init__(self): # 初始化操作 self.height=32 self.width=32 self.channels=3 # 字节数 self.image_bytes=self.height*self.width*self.channels # 图片像素数 self.label_bytes=1 # 标签数 self.all_bytes=self.label_bytes+self.image_bytes # 总字节数 def read_and_decode(self,file_list): # 1、构造文件名队列 file_queue=tf.train.string_input_producer(file_list) # 2、读取与解码 # 读取阶段 reader=tf.FixedLengthRecordReader(self.all_bytes) # key 文件名,value一个样本 key,value=reader.read(file_queue) print('key: ',key) print('value: ',value) # 解码阶段 decode=tf.decode_raw(value,tf.uint8) print('decode: ',decode) # 将目标值和特征值切片分开,即标签和通道分开。tf.slice(data,起始位置,个数) label=tf.slice(decode,[0],[self.label_bytes]) image=tf.slice(decode,[self.label_bytes],[self.image_bytes]) print('label: ',label) print('image: ',image) # 调整图片形状 image_reshaped=tf.reshape(image,shape = [self.channels,self.height,self.width]) print('image_reshaped: ',image_reshaped) # 转置,转成tf图片的表示格式 height,width,channels image_transposed=tf.transpose(image_reshaped,[1,2,0]) print('image_transposed: ',image_transposed) # 跳转图像类型,uint8转为float32,调高精度 image_cast=tf.cast(image_transposed,tf.float32) # 3、批处理 label_batch,image_batch=tf.train.batch([label,image_cast],batch_size = 100,num_threads = 1,capacity = 100) print('label_batch: ',label_batch) print('image_batch: ',image_batch) # 开启会话 with tf.Session() as sess: print('------------------开启会话------------------') # 开启线程 coord=tf.train.Coordinator() # 协调器 threads=tf.train.start_queue_runners(sess=sess,coord = coord) key_new,value_new,decode_new,label_new,image_new,image_reshaped_new,image_transposed_new,label_batch_new,image_batch_new=sess.run([key,value,decode,label,image,image_reshaped,image_transposed,label_batch,image_batch]) print('key_new: ',key_new) print('value_new: ',value_new) print('decode_new',decode_new) print('label_new',label_new) print('image_new',image_new) print('image_reshaped_new\n',image_reshaped_new) print('image_transposed_new\n',image_transposed_new) print('label_batch_new\n',label_batch_new) print('image_batch_new\n',image_batch_new) # 回收线程 coord.request_stop() coord.join(threads) return None if __name__ == '__main__': file_name=os.listdir('./data/cifar-10-batches-bin') # 构造路径 + 文件名的列表 file_list=[os.path.join('./data/cifar-10-batches-bin',file) for file in file_name if file[-3:]=='bin'] print('file_llist: ',file_list) #实例化Cifar类 cifar=Cifar() cifar.read_and_decode(file_list) ''' file_llist: ['./data/cifar-10-batches-bin\\data_batch_1.bin', './data/cifar-10-batches-bin\\data_batch_2.bin', './data/cifar-10-batches-bin\\data_batch_3.bin', './data/cifar-10-batches-bin\\data_batch_4.bin', './data/cifar-10-batches-bin\\data_batch_5.bin', './data/cifar-10-batches-bin\\test_batch.bin'] key: Tensor("ReaderReadV2:0", shape=(), dtype=string) value: Tensor("ReaderReadV2:1", shape=(), dtype=string) decode: Tensor("DecodeRaw:0", shape=(?,), dtype=uint8) label: Tensor("Slice:0", shape=(1,), dtype=uint8) image: Tensor("Slice_1:0", shape=(3072,), dtype=uint8) image_reshaped: Tensor("Reshape:0", shape=(3, 32, 32), dtype=uint8) image_transposed: Tensor("transpose:0", shape=(32, 32, 3), dtype=uint8) label_batch: Tensor("batch:0", shape=(100, 1), dtype=uint8) image_batch: Tensor("batch:1", shape=(100, 32, 32, 3), dtype=float32) ------------------开启会话------------------ key_new: b'./data/cifar-10-batches-bin\\data_batch_1.bin:0' value_new: b'\x06;+2Dbw\x8b\x91\x95\x95\x83}\x8e\x90\x89\x81\x89\x86|\x8b\x8b\x85\x88\x8b\x98\xa3\xa8\x9f\x9e\x9e\x98\x94\x10\x00\x123Xx\x80\x7f~tjeiqmpwmi}\x7fz\x83|y\x83\x84\x85\x85{wz\x19\x101Sn\x81\x82yqppji\x80|\x82\x7fzsx\x82\x83\x8b\x7f~\x7f\x82\x8e\x82vxm!&Wjsuriky}mq\x92\x85\x7fvu\x7fz\x84\x89\x][SME7;:A;.9h\x8cTH' decode_new [ 6 59 43 ... 140 84 72] label_new [6] image_new [ 59 43 50 ... 140 84 72] image_reshaped_new [[[ 59 43 50 ... 158 152 148] [ 16 0 18 ... 123 119 122] [ 25 16 49 ... 118 120 109] ... [ 96 34 26 ... 70 7 20] [ 96 42 30 ... 94 34 34] [116 94 87 ... 140 84 72]]] image_transposed_new [[[ 59 62 63] [ 43 46 45] [ 50 48 43] ... [216 184 140] [151 118 84] [123 92 72]]] label_batch_new [[6] [0] [2] [7] [2] .... [2] [8]] image_batch_new [[[[ 29. 43. 10.] [ 22. 36. 4.] [ 25. 37. 16.] ... [197. 219. 137.] [198. 219. 137.] [199. 222. 140.]] ....]]]] '''
TFRecords其实是一种二进制文件,虽然它不如其他格式好理解,但是它能更好的利用内存,更方便复制和移动,并且不需要单独的标签文件。即tfrecords 特征值和目标值是绑定在一起的
使用步骤:
文件格式 * . tfrecords
Example: features { feature{ key: "iamge" value:{ bytes_list { value: '\x06;+2Dbw\x8b\x91\x95\x95\x83}\x8e\x90\x89\x81\x89\x86|\x8b\x8b' } } } feature{ key: "label" value:{ int64_list { value: 9 } } } }
example = tf.train.Example(features=tf.train.Features(feature={
“image” : tf.train.Feature(bytes_list=tf.train.BytesList(value=[Bytes])),
“label” : tf.train.Feature(int64_list=tf.train.Int64List(value=[Value]))}))
这种example结构很好地实现了数据和标签(训练的类别标签)或者其他属性数据存储在同一个文件中
example.SerializeToString() 将example 序列化到本地
class Cifar(object): def __init__(self): # 初始化操作 self.height=32 self.width=32 self.channels=3 # 字节数 self.image_bytes=self.height*self.width*self.channels # 图片像素数 self.label_bytes=1 # 标签数 self.all_bytes=self.label_bytes+self.image_bytes # 总字节数 def read_and_decode(self,file_list): # 1、构造文件名队列 file_queue=tf.train.string_input_producer(file_list) # 2、读取与解码 # 读取阶段 reader=tf.FixedLengthRecordReader(self.all_bytes) # key 文件名,value一个样本 key,value=reader.read(file_queue) # 解码阶段 decode=tf.decode_raw(value,tf.uint8) # 将目标值和特征值切片分开,即标签和通道分开。tf.slice(data,起始位置,个数) label=tf.slice(decode,[0],[self.label_bytes]) image=tf.slice(decode,[self.label_bytes],[self.image_bytes]) # 调整图片形状 image_reshaped=tf.reshape(image,shape = [self.channels,self.height,self.width]) # 转置,转成tf图片的表示格式 height,width,channels image_transposed=tf.transpose(image_reshaped,[1,2,0]) # 跳转图像类型,uint8转为float32 image_cast=tf.cast(image_transposed,tf.float32) # 3、批处理 label_batch,image_batch=tf.train.batch([label,image_cast],batch_size = 100,num_threads = 1,capacity = 100) # 开启会话 with tf.Session() as sess: print('------------------开启会话------------------') # 开启线程 coord=tf.train.Coordinator() # 协调器 threads=tf.train.start_queue_runners(sess=sess,coord = coord) label_batch_new,image_batch_new=sess.run([label_batch,image_batch]) # 回收线程 coord.request_stop() coord.join(threads) return label_batch_new,image_batch_new def write_to_tfrecords(self,label_batch,image_batch): # 将样本的特征值和目标值写入tfrecords文件 with tf.python_io.TFRecordWriter('./temp/cifar10/cifar10.tfrecords') as tfWriter: # 循环构造example对象,并序列化写入文件 for i in range(label_batch.size): image=image_batch[i].tostring() # 序列化 label=label_batch[i][0] # [i][0]取出一维数组的值 example = tf.train.Example(features = tf.train.Features(feature = { "image": tf.train.Feature(bytes_list = tf.train.BytesList(value=[image])), "label": tf.train.Feature(int64_list = tf.train.Int64List(value=[label])) })) # 将序列化后的example写入到cifar10.tfrecords文件中 tfWriter.write(example.SerializeToString()) if __name__ == '__main__': file_name=os.listdir('./data/cifar-10-batches-bin') # 构造路径 + 文件名的列表 file_list=[os.path.join('./data/cifar-10-batches-bin',file) for file in file_name if file[-3:]=='bin'] print('file_llist: ',file_list) #实例化Cifar类 cifar=Cifar() label_batch,image_batch=cifar.read_and_decode(file_list) cifar.write_to_tfrecords(label_batch,image_batch)
读取这种文件整个过程与其他文件一样,只不过需要有个解析Example的步骤。从TFRecords文件中读取数据,可以使用tf.TFRecordReader的 tf.parse_single_example解析器。这个操作可以将Example协议内存块(protocol buffer)解析为张量。
#多了解析example的一个步骤
feature = tf.parse_single_example( values,features={
"image" : tf.FixedLenFeature([], tf.string),
"label" : tf.FixedLenFeature([], tf.int64)
})
tfrecords文件读取步骤分析
def write_to_tfrecords(self,label_batch,image_batch): # 将样本的特征值和目标值写入tfrecords文件 with tf.python_io.TFRecordWriter('./temp/cifar10/cifar10.tfrecords') as tfWriter: # 循环构造example对象,并序列化写入文件 for i in range(label_batch.size): image=image_batch[i].tostring() # 序列化 label=label_batch[i][0] # [i][0]取出一维数组的值 example = tf.train.Example(features = tf.train.Features(feature = { "image": tf.train.Feature(bytes_list = tf.train.BytesList(value=[image])), "label": tf.train.Feature(int64_list = tf.train.Int64List(value=[label])) })) # 将序列化后的example写入到cifar10.tfrecords文件中 tfWriter.write(example.SerializeToString()) def read_tfrecords(self,file_name): # 1、构造文件名队列 file_queue=tf.train.string_input_producer([file_name]) # 2、读取与解码 tfReader=tf.TFRecordReader() # TFRecord读取器 key,value=tfReader.read(file_queue) # 解析example feature=tf.parse_single_example(value,features = { "image":tf.FixedLenFeature([],tf.string), "label":tf.FixedLenFeature([],tf.int64) }) image=feature["image"] label=feature["label"] print('read_tf_image:\n',image) print('read_tf_label:\n',label) # 解码 image_decoded=tf.decode_raw(image,tf.uint8) print('image_decoded\n',image_decoded) # 图像形状调整,动态调整,调整为tf支持的格式 image_reshaped=tf.reshape(image_decoded,[self.height,self.width,self.channels]) print('image_reshaped\n',image_reshaped) # 3、批处理 image_batch,label_batch=tf.train.batch([image_reshaped,label],batch_size = 100,num_threads = 1,capacity = 100) print('image_batch\n',image_batch) print('label_batch\n',label_batch) # 4、开启会话 with tf.Session() as sess: # 开启线程 # 协调器 coord=tf.train.Coordinator() threads=tf.train.start_queue_runners(sess=sess,coord = coord) image_new,label_new,image_decoded_new,image_reshaped_new,image_batch_new,label_batch_new=sess.run([image,label,image_decoded,image_reshaped,image_batch,label_batch]) print('image_new\n',image_new) print('label_new\n',label_new) print('image_decoded_new\n',image_decoded_new) print('image_reshaped_new\n',image_reshaped_new) print('image_batch_new\n',image_batch_new) print('label_batch_new\n',label_batch_new) # 线程回收 coord.request_stop() coord.join(threads) return None if __name__ == '__main__': path='./temp/cifar10/cifar10.tfrecords' cifar.read_tfrecords(path)
**人工神经网络(Artificial Neural Network,简写为ANN)也简称为神经网络(NN)。**是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)结构和功能的计算模型。经典的神经网络结构包含三个层次的神经网络。分别为输入层,输出层以及隐藏层。
其中每层的圆圈代表一个神经元,隐藏层和输出层的神经元有输入的数据计算后输出,输入层的神经元只是输入
神经网络的特点:
那么为什么设计这样的结构呢?首先从一个最基础的结构说起,神经元。以前也称之为感知机。神经元就是要模拟人的神经元结构。
一个神经元通常具有多个树突,主要用来接受传入信息;而轴突只有一条,轴突尾端有许多轴突末梢可以给其他多个神经元传递信息。轴突末梢跟其他神经元的树突产生连接,从而传递信号。这个连接的位置在生物学上叫做**"突触”**。
感知机(PLA : Perceptron Learning Algorithm)
感知机就是模拟这样的大脑神经网络处理数据的过程。感知机模型如下图:
感知机是一种最基础的分类模型,类似于逻辑回归,不同的是,**感知机的激活函数用的是sign,而逻辑回归用的sigmoid。**感知机也具有连接的权重和偏置
神经网络解决多分类问题最常用的方法是设置n个输出节点,其中n为类别的个数。
任意事件发生的概率都在0和1之间,且总有某一个事件发生(概率的和为1)。如果将分类问题中“一个样例属于某一个类别”看成一个概率事件,那么训练数据的正确答案就符合一个概率分布。如何将神经网络前向传播得到的结果也变成概率分布呢? Softmax回归就是一个非常常用的方法。
softmax回归
softmax回归将神经网络输出转换成概率结果
softmax公式的理解
# 假设输出结果为:2.3,4.1,5.6
# softmax的计算输出结果为:
y1_p = e^2.3/(e^2.3+e^4.1+e^5.6)
y1_p = e^4.1/(e^2.3+e^4.1+e^5.6)
y1_p = e^5.6/( e^2.3+e^4.1+e^5.6)
这样子就把神经网络的输出也变成了一个概率输出
交叉熵损失函数: 衡量神经网络预测的概率和真实结果的概率之间的距离
交叉熵适合用于一个样本对应一个目标值
为了能够衡量距离,目标值需要进行one-hot编码,能与概率值――对应,如下图
计算
-[0log(0.10)+0log(0.05)+0log(0.15)+0log(0.10)+0log(0.05)+0log(0.20)+1log(0.10)…]
上述的结果为-1log(0.10),那么为了减少这一个样本的损失。神经网络应该怎么做?
答:提高对应目标值为1的位置输出概率大小。
损失大小
神经网络最后的损失为平均每个样本的损失大小。
即对所有样本的损失求和取其平均值
softmax、交叉熵损失API
tf.nn.softmax_cross_entropy_with_logits(labels=None, logits=None, name=None)
损失大小求平均
tf.reduce_mean(input_tensor)
计算张量的尺寸的元素平均值
交叉熵的优化:梯度下降
数据集介绍
文件说明:
网址: http://yann.lecun.com/exdb/mnist
特征值
Mnist数据集可以从官网下载,网址: http://yann.lecun.com/exdb/mnist/下载下来的数据集被分成两部分:55000行的训练数据集(mnist.train)和10000行的测试数据集 (mnist.test)。每一个MNIST数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。我们把这些图片设为"xs",把这些标签设为"ys”。训练数据集和测试数据集都包含xs和ys,比如训练数据集的图片是mnist.train.images,训练数据集的标签是mnist.train.labels。
我们可以知道图片是黑白图片,每一张图片包含28像素X28像素。我们把这个数组展开成一个向量,长度是28x28 = 784。因此,在MNIST训练数据集中,mnist.trajn.images是一个形状为[60000,784]的张量。
目标值
MNIST中的每个图像都具有相应的标签,目标值:0到9之间的数字表示图像中绘制的数字。用的是one-hot编码
nn[0,0,0,1,0,0,0,0,0,0] mnist.train.labels [55000,10]
minst数据获取API
TensorFlow框架自带了获取这个数据集的接口,所以不需要自行读取。
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('mnist_data', one_hot=True)
print(mnist.train.next_batch(1))
print(mnist.train.images[0]) # 查看特征值
print(mnist.train.labels[0]) # 目标值
mnist手写体识别网络层设计
我们采用只有一层,即最后一个输出层的神经网络,也称之为全连接(full connected) 层神经网络
全连接层计算:即构造权重和偏置
计算准确率:对One-hot概率 求平均值
全连接分析:
y=w1x1+w2x2+…+b
y_predict[None,10]=X[None,784]*weights[784,10]+bias[10]
error=tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)
def full_connection(): # 用全连接对手写数字进行识别 # 1、准备数据 mnist=input_data.read_data_sets("./data/mnist_data",one_hot = True) # 用占位符定义真实数据 X=tf.placeholder(dtype = tf.float32,shape = [None,784]) # 特征值 y_true=tf.placeholder(dtype = tf.float32,shape = [None,10]) # 真实值 # 2、构建模型 - 全连接 # y_predict[None,10]=X[None,784]*weights[784,10]+bias[10] weights=tf.Variable(initial_value = tf.random_normal(shape = [784,10],stddev = 0.01)) bias=tf.Variable(initial_value = tf.random_normal(shape = [10],stddev = 0.1)) y_predict=tf.matmul(X,weights)+bias # 3、构造损失函数 loss_list=tf.nn.softmax_cross_entropy_with_logits(logits = y_predict,labels = y_true) loss=tf.reduce_mean(loss_list) # 4、优化损失(梯度下降) optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss) # 5、计算准确率 tf.argmax()计算最大值所在列数 bool_list=tf.equal(tf.argmax(y_predict,axis = 1),tf.argmax(y_true,axis = 1)) accuracy=tf.reduce_mean(tf.cast(bool_list,tf.float32)) # 初始化变量 init = tf.global_variables_initializer() # 开启会话 with tf.Session() as sess: # 初始化变量 sess.run(init) # 开始训练 for i in range(100): # 获取真实值 image, label = mnist.train.next_batch(100) # 因为optimizer返回的是None 所以用_,来接 _, loss_value, accuracy_value = sess.run([optimizer, loss, accuracy], feed_dict = {X: image, y_true: label}) print("第%d次的损失为%f,准确率为%f" % (i + 1, loss_value, accuracy_value)) return None if __name__ == '__main__': # 如果你报numpy.ufunc size changed错误,尝试更新一下Numpy的版本 # pip install numpy==1.16.0 full_connection() ''' 第1次的损失为2.292725,准确率为0.160000 第2次的损失为2.331739,准确率为0.020000 ………………………… 第100次的损失为1.510217,准确率为0.730000 '''
输入层
隐藏层:卷积层、激活层、池化层、全连接层
输出层
神经网络(neural networks)的基本组成包括输入层、隐藏层、输出层。而卷积神经网络的特点在于隐藏层分为卷积层、激活层和池化层(pooling layer,又叫下采样层subsample)。
卷积神经网络的结构
卷积核又叫 filter、过滤器、模型参数、卷积单元
卷积神经网络中每层卷积层由若干卷积单元(卷积核)组成,每个卷积单元的参数都是通过反向传播算法最佳化得到的。
卷积运算的目的是特征提取,第一层卷积层可能只能提取一些低级的特征如边缘、线条和角等层级,更多层的网络能从低级特征中迭代提取更复杂的特征。
1、卷积核(Filter)的四大要素
卷积核个数
卷积核大小
卷积核步长
卷积核零填充大小
接下来我们通过计算案例讲解,假设图片是黑白图片(只有一个通道)
2、卷积核计算-大小
卷积核大小一般为 1 * 1 3 * 3 5 * 5
卷积核我们可以理解为一个观察的人,带着若干权重和一个偏置去观察,进行特征加权运算。
下图只有权重,少了偏置,一般情况下都要加上偏置!
通常的卷积核大小 1,3,5,是经过研究人员实验证明比较好的效果。这个人观察之后会得到一个运算结果,
那么这个人想观察所有这张图的像素怎么办?那就需要平移(即步长):
3、步长
需要去平移卷积核观察这张图片,需要的参数就是步长。
假设移动的步长为一个像素,那么最终这个人观察的结果以下图为例:
5x5的图片,3x3的卷积大小去一个步长运算得到3x3的大小观察结果
如果移动的步长为2那么结果是这样
5x5的图片,3x3的卷积大小,2个步长运算得到2x2的大小观察结果
4、卷积核个数
不同的卷积核带的权重和偏置都不一样,即随机初始化的参数
那么如果在某一层结构当中,不止是一个人观察,多个人(卷积核)一起去观察。那就得到多张观察结果。
也就是说,一个卷积核得到一个观察结果,多个卷积核就是多个观察结果
5、零填充大小
Filter观察窗口的大小和移动步长有时会导致超过图片像素宽度!
解决办法:
零填充就是在图片像素外围填充一圈值为0的像素。
6、计算输出大小
如果已知输入图片形状,卷积核数量,卷积核大小,以及移动步长,那么输出图片形状如何确定?
通过一个例子来理解上面的公式
计算案例:
1、假设已知的条件:输入图像32 * 32 * 1 , 50个Filter,大小为5 * 5,移动步长为1,零填充大小为1。请求出输出大小?
H2= (H1 -F +2P)/S + 1 =(32 - 5+2 * 1)/1 + 1 = 30
w2=(W1-F+2P)/S + 1 =(32 -5+2 * 1)/1 + 1 = 30
D2= K= 50(D2等于过滤器的数量K)
所以输出大小为[30,30,50]
2、假设已知的条件∶输入图像32 * 32 * 1 ,50个Filter,大小为3*3,移动步长为1,未知零填充。输出大小32 * 32,求零填充大小?
H2= (H1 -F +2P)/S + 1 = (32 - 3+2 * P)/1 +1 = 32
w2=(W1 -F+2P)/S+ 1 =(32-3+2 * P)/1 +1 = 32
故P=1
所以零填充大小为:1*1
7、多通道图片如何观察
如果是一张彩色图片,那么就有三种表分别为R,G,B。原本每个人需要带一个3x3或者其他大小的卷积核,现在需要带3张3x3的权重和一个偏置,总共就27个权重。最终每个人还是得出一张结果:
8、卷积网络API
随着神经网络的发展,大家发现原有的sigmoid等激活函数并不能达到好的效果,所以才去新的激活函数。
不同激活函数网站演示:http://playground.tensorflow.org
Relu函数
效果:
Relu激活函数API
为什么采用新的激活函数
Pooling层主要的作用是特征提取,通过去掉Feature Map中不重要的样本,进一步减少参数数量。即通过池化层尽可能保留图像的主要特征,不会影响图像模型的最终效果,减少模型的复杂度,避免过拟合现象。
Pooling的方法很多,通常采用最大池化
池化层计算: H2=(H1- F+2P)/S+1 ((高-过滤器大小+2零填充)/步长+1)
池化层也有窗口的大小以及移动步长,那么之后的输出大小怎么计算? 计算公式同卷积计算公式一样
计算:224x224x64,窗口为2,步长为2 输出结果?
H2 =(224 -2+ 2 * 0)/2 +1 = 112
w2 =(224- 2+ 2 * 0)/2 +1 =112
通常池化层采用2x2大小、步长为2窗口,零填充为默认P=0
例子2:
输入图片大小为200×200,依次经过一层卷积(kernel size 5×5,padding 1,stride 2) ,
pooling (kernel size 3×3,padding 0,stride 1),又一层卷积(kernel size 3×3,padding 1,stride 1)之后,
输出特征图大小为:
A.95
B.96
C.97
D.98
E.99
F.100
答案:C
h2=99 w2=99 d2=5 h3=97 d3=3 h4=97 d4=3
注:卷积层向下取整,池化层向上取整
池化层API
全连接层计算:即构造权重和偏置
如全连接:
y=w1x1+w2x2+…+b
y_predict[None,10]=X[None,784]*weights[784,10]+bias[10]
weights=tf.Variable(initial_value = tf.random_normal(shape = [784,10],stddev = 0.01))
bias=tf.Variable(initial_value = tf.random_normal(shape = [10],stddev = 0.1))
y_predict=tf.matmul(X,weights)+bias
自己设计一个简单的卷积神经网络做图像识别。由于神经网络的黑盒子特性,如果想自己设计复杂网络通常还是比较困难的,可以使用一些现有的网络结构如之前的GoogleNet、vGG等等。
简单的网络结构
具体参数
经过每一层图片数据大小的变化需要确定,Mnist输入的每批次若干图片数据[None,784],如果要经过卷积计算,需要变成[None, 28, 28,1] , 28 x 28=784
卷积网络API: tf.nn.conv2d( input,filter, strides=,padding=)
第一层卷积大层
c
32个filter 大小F:5 * 5 步长S:1 padding=“SAME”
padding=same 指输出图像和输入一样,故宽高都跟原来的值一样
输入图片形状 [betch, heigth,width, channel] ,要求:类型为float32,64
input:输入图像[None,28,28,1]
filter:
变量initial_value=random_normal(shape=[F,F,channels,K])
weights = tf.Variable(initial_value=tf.random_normal(shape=[5,5,1,32]))
bias = tf.Variable(initial_value=tf.random_normal(shape=[32]))
strides: 步长1
[1,1,1,1]
padding: "SAME”
SAME”︰越过边缘取样
“VALID”":不越过边缘取样
输出形状:因为是padding=same,故输出宽高跟输入一致
激活层: Relu tf.nn.relu(features, name=None)
池化层: 大小2*2 步长2 ,默认padding=0 tf.nn.max_pool(value,ksize=, strides=, padding=,name=None)
输出形状:[None,14,14,32]
第二层卷积大层
卷积层: tf.nn.conv2d( input,filter, strides=,padding=)
64个filter 大小5 * 5 步长:1 padding=“SAME”
输入现状: [None,14,14,32]
filter:
变量initial_value=random_normal(shape=[F,F,channels,K])
weights = tf.Variable(initial_value=tf.random_normal(shape=[5,5,32,64]))
bias = tf.Variable(initial_value=tf.random_normal(shape=[64]))
strides: 步长1
[1,1,1,1]
padding: "SAME”
SAME”︰越过边缘取样
“VALID”":不越过边缘取样
输出形状:因为是padding=same,故输出宽高跟输入一致
激活层: Relu tf.nn.relu(features, name=None)
池化层: 大小2*2 步长2 ,默认padding=0 tf.nn.max_pool(value,ksize=, strides=, padding=,name=None)
输出形状:[None,7,7,64]
全连接层
CNN-Minst卷积神经网络简单案例:
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data def create_weights(shape): # 定义权重和偏置 stddev 标准差 return tf.Variable(initial_value = tf.random_normal(shape = shape,stddev = 0.01)) def create_model(x): # 构建卷积神经网络模型 # 1、第一卷积大层 with tf.variable_scope('conv1'): # 卷积层 # 将x[None,784]进行形状上的修改 -1 会自动统计有多少张betch input_x=tf.reshape(x,shape = [-1,28,28,1]) # 定义32个filter和偏置 conv1_weights=create_weights(shape = [5,5,1,32]) conv1_bias=create_weights(shape = [32]) conv1_x=tf.nn.conv2d(input = input_x,filter = conv1_weights,strides = [1,1,1,1],padding="SAME")+conv1_bias # 激活层 relu1_x=tf.nn.relu(conv1_x) # 池化层 pool1_x=tf.nn.max_pool(value =relu1_x,ksize = [1,2,2,1],strides = [1,2,2,1],padding = "SAME") # 2、第一卷积大层 with tf.variable_scope('conv2'): # 卷积层 # 定义64个filter和偏置 conv2_weights = create_weights(shape = [5, 5, 32, 64]) conv2_bias = create_weights(shape = [64]) conv2_x = tf.nn.conv2d(input = pool1_x, filter = conv2_weights, strides = [1, 1, 1, 1],padding = "SAME") + conv2_bias # 激活层 relu2_x = tf.nn.relu(conv2_x) # 池化层 pool2_x = tf.nn.max_pool(value = relu2_x, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = "SAME") # 全连接层 with tf.variable_scope('full_connection'): # 改变形状,修改为二维数组类型 x_fc=tf.reshape(pool2_x,shape = [-1,7*7*64]) weights_fc=create_weights(shape = [7*7*64,10]) bias_fc=create_weights(shape = [10]) y_predict=tf.matmul(x_fc,weights_fc)+bias_fc return y_predict def full_connection(): # 用全连接对手写数字进行识别 # 1、准备数据 mnist=input_data.read_data_sets("./data/mnist_data",one_hot = True) # 用占位符定义真实数据 X=tf.placeholder(dtype = tf.float32,shape = [None,784]) # 特征值 y_true=tf.placeholder(dtype = tf.float32,shape = [None,10]) # 真实值 # 2、构建模型 - 全连接 y_predict=create_model(X) # 3、构造损失函数 loss_list=tf.nn.softmax_cross_entropy_with_logits(logits = y_predict,labels = y_true) loss=tf.reduce_mean(loss_list) # 4、优化损失(梯度下降) optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss) # 默认0.01最多 # 调优,修改学习率,优化器等 # optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(loss) # Adam优化器 # optimizer=tf.train.AdamOptimizer(learning_rate = 0.01).minimize(loss) # 5、计算准确率 tf.argmax()计算最大值所在列数 bool_list=tf.equal(tf.argmax(y_predict,axis = 1),tf.argmax(y_true,axis = 1)) accuracy=tf.reduce_mean(tf.cast(bool_list,tf.float32)) # 初始化变量 init = tf.global_variables_initializer() # 开启会话 with tf.Session() as sess: # 初始化变量 sess.run(init) # 开始训练 for i in range(300): # 获取真实值 image, label = mnist.train.next_batch(100) # 因为optimizer返回的是None 所以用_,来接 _, loss_value, accuracy_value = sess.run([optimizer, loss, accuracy], feed_dict = {X: image, y_true: label}) print("第%d次的损失为%f,准确率为%f" % (i + 1, loss_value, accuracy_value)) return None # 准确率 比较输出的结果最大值与真实值最大值所在的位置 # print(mnist.train.next_batch(1)) # print(mnist.train.images[0]) # 查看特征值 # print(mnist.train.labels[0]) # 目标值 # one - hot 0 1 ...9 if __name__ == '__main__': # 如果你报numpy.ufunc size changed错误,尝试更新一下Numpy的版本 # pip install numpy==1.16.0 full_connection() ''' 第66次的损失为2.066249,准确率为0.200000 第67次的损失为1.938220,准确率为0.310000 第68次的损失为1.739915,准确率为0.450000 第69次的损失为1.615815,准确率为0.470000 '''
网络的优化和改进
def weight__variables(shape ) :
w = tf.Variable(tf.random_normal(shape=shape,mean=0.0,stddev=0.1) # 调整平均值和标准差
return w
卷积神经网络结构在imagenet比赛对比
卷积网络其它用途
步骤分析
步骤分析
特征值目标值–模型
特征值:6000张图片-目标值―—对应
读取图片数据
解析CSV文件,建立文件名和标签值对应表格
将一个样本的特征值和目标值一一对应
建立卷积神经网络模型== 》得出y_predict
计算sigmoid交叉嫡损失
优化
计算准确率
import tensorflow as tf import pandas as pd import numpy as np import glob # 1、读取图片数据 # key, value = read(file_queue) # key: 文件名 - labels.csv - 目标值value:一个样本的内容 def read_pic(): #1、构建文件名队列 file_names=glob.glob('./data/GenPics/*.jpg') file_queue=tf.train.string_input_producer(file_names) #2、读取与解码 reader=tf.WholeFileReader() filename,image=reader.read(file_queue) #解码阶段 decoded_image=tf.image.decode_jpeg(image) #更新形状,将图片形状确定下来 decoded_image.set_shape([20,80,3]) #修改图片的类型 cast_image=tf.cast(decoded_image,tf.float32) #3、批处理 filename_batch,image_batch=tf.train.batch([filename,cast_image],batch_size = 100,num_threads = 1,capacity = 200) return filename_batch,image_batch # 2、解析CSV文件,建立文件名和标签值对应表格 def parse_csv(): # 读取文件 csv_data=pd.read_csv('./data/GenPics/labels.csv',names = ['file_num','chars'],index_col = 'file_num') #根据字母生成对应数字 # NZPP [13,25,15,15] labels=[] for label in csv_data['chars']: letter=[] for word in label: # A在26字母中的序号为0 B为1 letter.append(ord(word)-ord('A')) # ord() 返回对应的ASCII数值 labels.append(letter) csv_data['labels']=labels # 更新labels列的内容 return csv_data # 3、将一个样本的特征值和目标值一一对应 # 通过文件名查表(csv_data) def filename2label(filenames,csv_data): labels=[] for file_name in filenames: file_num="".join((list(filter(str.isdigit,str(file_name))))) # 获取csv的序号,从而找到目标值 target_labels=csv_data.loc[int(file_num),'labels'] # 目标值 labels.append(target_labels) return np.array(labels) # 4、建立卷积神经网络模型 == 》得出y_predict def create_weights(shape): # 定义权重和偏置 stddev 标准差 return tf.Variable(initial_value = tf.random_normal(shape = shape,stddev = 0.01)) def create_model(x): # 构建卷积神经网络模型 # x: [None,20,80,3] # 1、第一卷积大层 with tf.variable_scope('conv1'): # 卷积层 # 定义32个filter和偏置 conv1_weights=create_weights(shape = [5,5,3,32]) conv1_bias=create_weights(shape = [32]) conv1_x=tf.nn.conv2d(input = x,filter = conv1_weights,strides = [1,1,1,1],padding="SAME")+conv1_bias # 激活层 relu1_x=tf.nn.relu(conv1_x) # 池化层 pool1_x=tf.nn.max_pool(value =relu1_x,ksize = [1,2,2,1],strides = [1,2,2,1],padding = "SAME") # 2、第一卷积大层 with tf.variable_scope('conv2'): # 卷积层 # 定义64个filter和偏置 conv2_weights = create_weights(shape = [5, 5, 32, 64]) conv2_bias = create_weights(shape = [64]) conv2_x = tf.nn.conv2d(input = pool1_x, filter = conv2_weights, strides = [1, 1, 1, 1],padding = "SAME") + conv2_bias # 激活层 relu2_x = tf.nn.relu(conv2_x) # 池化层 pool2_x = tf.nn.max_pool(value = relu2_x, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = "SAME") # 全连接层 with tf.variable_scope('full_connection'): # 改变形状,修改为二维数组类型 # # 输入[None,10,40,32]-->[None,5,20,64] #[None, 5, 20, 64]-->[None, 5 * 20 * 64] #[None,5 * 20 * 64]*[5 * 20 * 64,4 * 26] = [None,4 * 26] x_fc=tf.reshape(pool2_x,shape = [-1,5*20*64]) weights_fc=create_weights(shape = [5*20*64,4*26]) bias_fc=create_weights(shape = [4*26]) y_predict=tf.matmul(x_fc,weights_fc)+bias_fc return y_predict if __name__ == '__main__': filename,image=read_pic() csv_data=parse_csv() # 1、准备数据 x=tf.placeholder(tf.float32,shape = [None,20,80,3]) y_true=tf.placeholder(tf.float32,shape = [None,4*26]) # 2、构建模型 y_predict=create_model(x) # 3、构建损失函数 loss_list=tf.nn.sigmoid_cross_entropy_with_logits(labels = y_true,logits = y_predict) loss=tf.reduce_mean(loss_list) # 4、优化损失 # optimizer=tf.train.GradientDescentOptimizer(learning_rate = 0.01).minimize(loss) # 梯度下降,最小化 optimizer=tf.train.AdamOptimizer(learning_rate = 0.1).minimize(loss) # Adam优化器,最小化 # 5、计算准确率 equal_list=tf.reduce_all(tf.equal(tf.argmax(tf.reshape(y_predict,shape = [-1,4,26]),axis = 2), tf.argmax(tf.reshape(y_true, shape = [-1, 4,26]), axis = 2)),axis=1) accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32)) # 初始化变量 init=tf.global_variables_initializer() # 开启会话 with tf.Session() as sess: sess.run(init) # 开启线程 coor=tf.train.Coordinator() threads=tf.train.start_queue_runners(sess = sess,coord = coor) for i in range(150): filename_value,image_value=sess.run([filename,image]) labels=filename2label(filename_value,csv_data) # 将一个样本的特征值和目标值一一对应 # 将目标值转换为one-hot编码 labels_value=tf.reshape(tf.one_hot(labels,depth = 26),[-1,4*26]).eval() _,error,accuracy_value=sess.run([optimizer,loss,accuracy],feed_dict = {x:image_value,y_true:labels_value}) print('第%d次训练损失为%f,准确率为%f'%(i+1,error,accuracy_value)) # 回收线程 coor.request_stop() coor.join(threads)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。