深度学习——神经网络
构建网络的总原则
一、增大网络容量,直到过拟命
二、采取措施抑制过拟合
三、继续增大网络容量,直到过拟合
线性回归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import kerasimport numpy as npimport matplotlib.pyplot as pltx = np.linspace(0 ,80 ,50 ) y = 3 *x + np.random.randn(50 )*15 plt.scatter(x,y) from keras import layersmodel = keras.Sequential() model.add(layers.Dense(1 ,input_dim=1 )) model.summary() model.compile(optimizer='adam' , loss='mse' ) model.fit(x,y,epochs=2000 ) predict_y = model.predict(x) plt.scatter(x,y,s=10 ,c='r' ) plt.plot(x,predict_y)
非线性回归
激活函数
softmax
S i = e i ∑ j e j S_{i}=\frac{e^{i}}{\sum_{j} e^{j}} S i = ∑ j e j e i
sigmod:
logistic:
范围是[0,1]
f ( t ) = e t e t + 1 = 1 1 + e − t f(t)=\frac{\mathrm{e}^{t}}{\mathrm{e}^{t}+1}=\frac{1}{1+\mathrm{e}^{-t}} f ( t ) = e t + 1 e t = 1 + e − t 1
reLU
f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f ( x ) = m a x ( 0 , x )
tanh
跟sigmoid函数很像,但是范围是[-1,1],而不是[0,1],实质是sigmoid函数平移
tanh ( x ) = sinh x cosh x = e x − e − x e x + e − x \tanh(x)=\frac{\sinh x}{\cosh x}=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}} tanh ( x ) = cosh x sinh x = e x + e − x e x − e − x
TensorFlow中其他的函数:
●tf.nn.elu(x): 指数线性单元; 如果输入小于0, 返回exp(x)-1; 否
则, 返回x;
●tf.softsign(x): 返回x/(abs(x)+1);
●tf.nn.bias_add(value,bias): 增加一个bias到value。
Tensorflow:
张量——数据 :
多维数组,阶:张量的维数
计算图——神经网络
搭建神经网络的计算过程,只搭建,不运算
会话——执行计算图===>优化线上的权重====>权重
神经网络实现过程
1.准备数据集,提取特征,作为输入
2.搭建NN结构,从输入到输出==>(NN前向传播)
3.大量特征数据喂给NN,迭代优化NN参数==>(NN反向传播)
4.使用训练好的模型预测和分类
>八股:准备,前传,后传,迭代<
1 2 x = tf.placehold(tf.float32,shape=(1 ,2 )) sess.run(要计算的节点,feed_dict={x:[[1.3 ,2.0 ]]})
1 2 Init_op = tf.global_variables_initializer() sess.run(Init_op)
y = matmul(x,w1)`相乘
《TensorFlow机器学习项目实战》笔记
张量
TensorFlow基于张量数据管理。 张量是数学领域的概念, 并且被开
发为向量和矩阵的线性代数项的泛化。 一个张量就是一个张量类的实例, 是绑定了相关运算的一个特定类型的多维数组 。
张量的属性
有一个静态的类型和动态的维数
只有张量类型的对象才能在计算图的节点中
传递。
秩rank
数据类型type
形状shape
numpy数组到TensorFlow张量
TensorFlow与numpy是可互操作的, 通常调用eval()函数会返回
numpy对象。因为张量对象只是一个操作结果的符号化句柄, 所以它并不持有该操作的结果 ,必须使用eval()方法来获得实际的
值
1 2 3 4 5 6 7 8 import tensorflow as tf import numpy as np sess = tf.Session() x_data = np.array([[1. ,2. ,3. ], [3. ,2. ,6. ]]) x = tf.convert_to_tensor(x_data, dtype=tf.float32)
tf.convert_to_tensor``: 该方法将Python对象转化为tensor对象。 它的
输入可以是tensor对象、 numpy数组、 Python列表和Python标量。
数据流图(data flow graph)
数据流图是完整的TensorFlow计算
节点(node) 表示操作(operation) ,实现数学运算, 同时也表示数据或变量的供给(feed) , 或输出结果 。一旦其输入边缘上的所有张量都到位, 则开始异步地并行执行
边(edge) 表示各操作之间流通的数据 ,描述节点之间的输入/输出关系。 这些数据边缘专门传输张量
计算图(computation graph)
由用户在创建张量(tensor) 和操作(op
有用的操作对象方法如下:
●tf.Operation.type: 返回操作的类型(例如, MatMul) ;
●tf.Operation.inputs: 返回表示操作的输入张量对象列表;
●tf.Graph.get_operations(): 返回计算图中的操作列表;
●tf.Graph.version: 返回计算图的版本信息。
变量
正如字面意思所示,是个变化的量。在TensorFlow具体表现为需要更新的参数
在大多数计算中, 会多次执行计算图。 大多数张量的生存周期不会
超过单次执行周期。 然而, 变量是一种特殊的操作, 它返回一个持久
的、 可变的张量的句柄, 存活于多次计算图执行之中。 对于TensorFlow
的机器学习应用, 模型的参数通常存储在变量中, 并且在运行模型的训
练阶段被更新。
placehold
给之后喂给的数据占位
会话
客户端程序通过创建会话(Session)与TensorFlow系统交互。
Session对象是运行环境的表示。Session对象开始为空,当程序员创建不同的操作和张量时,它们将被自动添加到Session,直到Run方法被调用,才开始运算。
Run方法输入是需要计算的操作,以及一组可选的张量,用来代替图中某些节点的输出。
如果我们调用这个方法,并且有命名操作所依赖的操作,Session对象将执行所有这些操作,然后继续执行命名操作。
用以下简单的代码可以创建一个会话:
s=tf.Session()
矩阵运算
转置、 乘法、 获取行列式和逆
1 2 3 4 tf. transpose(x). eval() tf. matmul(x,y). eval() tf. matrix determinant(floatx). eval() tf.matrix_inverse(floatx).eval()
约简(reduction) 是一种跨维度张量操作, 计算结果比原张量缩减
一个维度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 In [1 ]: import tensorflow as tf In[2 ]: sess=tf. InteractiveSession() In[3 ]:x=tf. constant([[1 ,2 ,3 ], [3 ,2 ,1 ], [-1 ,2 ,-3 ]]) In[5 ]: tf.reduce_prod(x, reduction_indices=1 ). eval() 0 ut[5 ]: array([6 ,6 ,-6 ], dtype=int32) In [6 ]: tf. reduce_min(x, reduction_indices=1 ). eval() 0 ut[6 ]: array([1 ,1 ,-3 ], dtype=int32) In [7 ]: tf. reduce_max(x, reduction_indices=1 ). eval() 0 ut[7 ]: array([3 ,3 ,-1 ], dtype=int32) In [8 ]: tf. reduce_mean(x, reduction indices=1 ). eval() 0 ut[8 ]: array([ 2 ,2 ,-2 ], dtype=int32) In[9 ]: tf. reduce_all(boolean_tensor, reduction_indices=1 ). eval() Out[9 ]: array([ False , False , False ], dtype=bool) In [10 ]: tf. reduce_any(boolean_tensor,
序列实用程序包括诸如argmin和argmax(显示维度的最小和最大
值) , listdiff(显示列表之间的交集的补码) , where(显示张量上的真
实值的索引) 和unique(在列表上去除重复的元素) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import tensorflow as tf sess=tf. InteractiveSession()x=tf. constant([[2 ,5 ,3 ,-5 ], …:[0 ,3 ,-2 ,5 ],……:[4 ,3 ,5 ,3 ],…:[6 ,1 ,4 ,0j j) listx=tf. constant([1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ]) listy=tf. constant([4 ,5 ,8 ,9 ]) boolx=tf. constant([[ True , False ], [ False , True ]]) tf. argmin(x,1 ). eval() >>> array([3 ,2 ,1 ,3 ]) tf. argmax(x,1 ). eval() >>> array([1 ,3 ,2 ,0 ]) tf. listdiff(listx, listy)[0 ]. eval() >>> array([1 ,2 ,3 ,6 ,7 ], dtype=int32) tf.where(boolx). eval() >>> array([[o,0 ],[1 ,1 ]]) tf. unique(listx)[0 ]. eval() >>> array([1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ], dtype=int32)
形状变换 :
例如squeeze和expand_dims。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 In [1 ]: import tensorflow as tf In [2 ]: sess=tf. InteractiveSession() In [3 ]:x=tf. constant([[2 ,5 ,3 ,-5 ], ……:[0 ,3 ,-2 ,5 ], …:[4 ,3153 , …:[6 ,1 ,4 ,0 ]]) tf. shape(x). eval() >>> array([4 ,4 ], dtype=int32)tf. size(x). eval() >>>16 tf. rank(x). eval() >>>2 tf. reshape(x,[8 ,2 ]). eval() converting to a 10 ×2 matrix >>> array([[ 2 ,5 ], [3 ,-5 ], [0 ,3 ], [-2 ,5 ], [1 ,4 ], [3 ,1 ], [5 ,3 ], [6 ,1 ], [4 ,0 ]], dtype=int32) tf. squeeze(x). eval() >>> array([[ 2 ,5 ,3 ,-5 ],[0 ,3 ,-2 ,5 ], 4 ,3 ,5 ,3 ],[6 ,1 ,4 ,0 ]], dtype=int32) tf. expand_dims(x,1 ). eval() >>> array([[[ 2 ,5 ,3 ,-5 ]], [[ 0 ,3 ,-2 ,5 ]], [[4 ,3 ,5 ,3 ]], [i 6 ,1 ,4 ,0j ji, dtype=int32)
切片(slicing) 和连接(joining) :提取矩阵切片、 拆分、 添加填充(add padding) , 以及打包(pack) 和解包(unpack) 行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import tensorflow as tf sess=tf. InteractiveSession()t_matrix=tf. constant([[1 ,2 ,3 ], ……:[4 ,5 ,6 ], …:[7 ,8 ,9 ]]) t_array=tf. constant([1 ,2 ,3 ,4 ,9 ,8 ,6 ,5 ]) t array2=tf. constant([2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ]) tf. slice(t _matrix,[1 ,1 ],[2 ,2 ]). eval() >>>array([[5 ,6 ], [8 ,9 ]], dtype=int32) tf. split(0 ,2 ,t_array) >>> [<tf. Tensor ' split:0' shape=(4 ,) dtype=int32>, <tf. Tensor ' split:1' shape=(4 ,) dtype=int32>] tf. tile([1 ,2 ],[3 ]). eval() >>> array([1 ,2 ,1 ,2 ,1 ,2 ], dtype=int32)tf. pad(t_matrix,[[0 ,1 ],[2 ,1 ]]). evai() >>> array(i[o,o,1 ,2 ,3 ,0 ],[0 ,0 ,4 ,5 ,6 ,0 ],[o.0 .7 .8 .9 .01 . [o,o,o,0 ,0 ,0 ]], dtype=int32) tf. concat(0 ,[t_array, t_array2]). eval() >>> array([1 ,2 ,3 ,4 ,9 ,8 ,6 ,5 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ], dtype=int32)tf. pack([t_array,t_array2]). eval() 0 ut[11 ]:array([[1 ,2 ,3 ,4 ,9 ,8 ,6 ,5 ],[2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ]], dtype=int32) sess.run(tf. unpack(t_matrix)) >>>[array([1 ,2 ,3 ],dtype=int32), array([4 ,5 ,6 ],dtype=int32), array([7 ,8 ,9 ];dtype=int32) In [13 ]: tf. reverse(t_matrix, [ False , True ]). eval() 0 ut[13 ]: array([[3 ,2 ,1 ],[6 ,5 ,41 ; 9 ,8 ,7 ]], dtype=int32)
从磁盘读取信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import tensorflow as tfsess=tf.Session() filename_queue= tf.train.string_input_producer( tf.train.match_filenames_once("./*.csv" ), shuffle=True ) reader=tf.TextLineReader(skip_header_lines=1 ) key, value=reader.read(filename_queue) record_defaults=[[0. ],[0. ],[0 ],[0. ],["" ]] col1, col2, col3, col4, col5= tf.decode_csv(value, record_defaults=record_defaults) records to tensors.Each features=tf.pack([ col1, col2, col3, col4]) tf.initialize_all_variables().run(session=sess) coord=tf.train.Coordinator() threads= tf.train.start_queue_runners(coord=coord, sess=sess) for iteration in range(0 ,5 ):example=sess.run([ features]) print(example) coord.request_stop() coord.join(threads) import tensorflow as tf sess=tf.Session()filename_queue= tf.train.string_input_producer(tf.train.match_filenames_once('./blue_jay.jpg' )) reader=tf.WholeFileReader() key, value= reader.read(filename_queue) image=tf.image.decode_jpeg(value) fliplmageUpDown=tf.image.encode _jpeg(tf.image.fli p_up_down(image)) fliplmageleftRight=tf.image.encode_jpeg(tf.image.flip_left_right(image)) tf.initialize_all_variables().run(session=sess) coord=tf.train.Coordinator() threads= tf.train.start_queue_runners(coord=coord, sess=sess) example=sess.run(fliplmageLeftRight) print example file=open ("flippedUpDown.jpg" ,"wb+" )file.write (fliplmageUpDown.eval(session=sess)) file.close() file=open ("flippedLeftRight.jpg" ,"wb+" ) file.write (fliplmageLeftRight.eval(session=sess)) file.close()
流程:
创建一个文件队列对象:tf.train.string_input_producer(tf.train.match_filenames_once('xxx'))
创建一个reader对象
读取,并解码
提取特征
initialize_all_variables->Coordinator->start_queue_runners->run
logit函数
logit ( p ) = log ( p 1 − p ) \operatorname{logit}(\mathrm{p})=\log \left(\frac{\mathrm{p}}{1-\mathrm{p}}\right) l o g i t ( p ) = log ( 1 − p p )
该函数实现了从区间[0,1]到区间(-∞,+∞)之间的映射。 那么我们只要将y用一个输入的线性函数替换, 那么就实现了输入的线性变化和区间[0,1]之间的映射。
logistic函数
对数几率函数的逆函数
logit − 1 ( α ) = logistic ( α ) = 1 1 + exp ( − α ) = ep ( α ) exp ( α ) + 1 \operatorname{logit}^{-1}(\alpha)=\operatorname{logistic}(\alpha)=\frac{1}{1+\exp (-\alpha)}=\frac{\operatorname{ep}(\alpha)}{\exp (\alpha)+1} l o g i t − 1 ( α ) = l o g i s t i c ( α ) = 1 + exp ( − α ) 1 = exp ( α ) + 1 e p ( α )
这是一个Sigmoid函数。
Logistic函数将使得我们能够在我们的回归任务表示为二项选择。
σ ( t ) = e t e t + 1 = 1 1 + e − t \sigma(t)=\frac{\mathrm{e}^{t}}{\mathrm{e}^{t}+1}=\frac{1}{1+\mathrm{e}^{-t}} σ ( t ) = e t + 1 e t = 1 + e − t 1
一般的解释就是t为一个独立变量, 该函数将t映射到区间[0,1]之
间。 但是我们提升了这个模型, 将t转变为变量x的一个线性映射(当x
是一个多变量的向量时, t就是该向量中各个元素的线性组合) 。
我们可以将t表示如下:
t=wx+b
我们就能够得到以下方程 logit ( p ) = In ( p 1 − p ) = w x + b \operatorname{logit}(\mathrm{p})=\operatorname{In}\left(\frac{p}{1-p}\right)=w x+b l o g i t ( p ) = I n ( 1 − p p ) = w x + b
对于所有的元素, 我们计算了回归方程, 得出如下概率。 p ^ = e β 0 + β 1 x 1 + e β 0 + β 1 x \hat{p}=\frac{\mathrm{e}^{\beta_{0}+\beta_{1} x}}{1+\mathrm{e}^{\beta_{0}+\beta_{1} x}} p ^ = 1 + e β 0 + β 1 x e β 0 + β 1 x
线性函数的参数起什么作用呢? 它们可以改变直线的斜率和
Sigmoid函数零的位置。 通过调整线性方程中的参数, 来缩小预测值与
真实值之间的差距。
Logistic函数的属性
函数空间中每个曲线都可以被描述成它所应用的可能目标。 具体到Logistic函数:
●事件的可能性p依赖于一个或者多个变量。 比如, 根据之前的资
历,预测获奖的可能性。
●对于特定的观察, 估算事件发生的可能性。
●预测改变独立变量对二项响应的影响。
●通过计算可能性, 将观测分配到某个确定的类。
损失函数
loss = − ∑ i y i ∙ log ( y p r e d i ) + ( 1 − y i ) ∙ log ( 1 − y p r e d i ) =-\sum_{i} y_{i} \bullet \log \left(y p r e d_{i}\right)+\left(1-y_{i}\right) \bullet \log \left(1-y p r e d_{i}\right) = − ∑ i y i ∙ log ( y p r e d i ) + ( 1 − y i ) ∙ log ( 1 − y p r e d i )
该损失函数的主要性质就是偏爱相似行为, 而当误差超过0.5的时
候, 惩罚会急剧增加。
多类分类应用——Softmax回归
当我们面对多于二类的情况, 通常有两种方法: 一对多和一对所
有。
●第一类技术计算多个模型。 针对每个类都计算一个“一vs所有
(one against all) ”的概率。
●第二类技术只计算出一个概率集合, 每个概率表示属于其中某一
类的可能性。
●第二种技术的输出是Softmax回归格式, 这是Logistic回归对于n类
的泛化。
损失函数
l o s s = ∑ i ∑ c y c ∙ log ( y p r e d c ) = ∑ i ∑ c y c ∙ e − x c ∑ j = 0 c − 1 log ( e − x j ) loss=\sum_{i} \sum_{c} y_{c} \bullet \log \left(y p r e d_{c}\right)=\sum_{i} \sum_{c} y_{c} \bullet \frac{e^{-x_{c}}}{\sum_{j=0}^{c-1} \log \left(e^{-x_{j}}\right)} l o s s = ∑ i ∑ c y c ∙ log ( y p r e d c ) = ∑ i ∑ c y c ∙ ∑ j = 0 c − 1 log ( e − x j ) e − x c
感知器算法
简单来说就是一个二元分类函数
简化版的感知器算法如下:
① 以一个随机分布初始化权值和偏差(通常比较小) ;
② 选择一个输入向量, 并将其放入神经网络中;
③ 将输入与权重相乘, 并加上偏差, 计算网络的输出y’;
④ 感知器的函数如下:
f ( x ) = { 1 i f w ⋅ x + b > 0 0 o t h e r w i s e f(x)=\left\{\begin{array}{ll}{1} & {if \; w \cdot x+b>0} \\ {0} & otherwise \end{array}\right. f ( x ) = { 1 0 i f w ⋅ x + b > 0 o t h e r w i s e
⑤ 如果y′≠y, 将权重wi加上Δw=yxi;
⑥ 返回第②步。
TensorFlow中损失优化方法
●tf.train.GradientDescentOptimizer(learning_rate, use_locking,
name): 原始梯度下降方法, 唯一参数就是学习率。
●tf.train.AdagradOptimizer: 自适应调整学习率, 累加历史梯度的平
方, 作为分母, 防止有些方向的梯度值过大, 提高优化效率, 善于处理
稀疏梯度。
●tf.train.AdadeltaOptimizer: 扩展AdaGrad优化方法, 只累加最近的
梯度值, 而不对整个历史上的梯度值进行累加。
●tf.train.AdamOptimizertf.train.AdamOptimizer. (learningrate, beta1,
beta2, epsilon, use locking, name): 梯度的一阶矩估计和二阶矩估计动态
调整每个参数的学习率。 Adam是自适应矩估计(Adaptive Moment
Estimation) 的首字母缩写。
Sklearn预处理函数
我们看一些下面的Sklearn数据预处理函数:
●preprocessing.StandardScaler(): 数据正规化(Normalization) 是机
器学习估计的一个常见要求, 为了模型能更好地收敛, 我们通常会将数
据集预处理到一个零均值单位方差的高斯状分布。 通常, 我们会将数据
的各个维度都减去它的均值, 然后乘上一个非零的数。 这个非零的数就
是数据集的标准差。 对于该任务, 我们直接使用StandardScaler, 它已经
实现了我们上面提到的操作。 它也保留了变换操作, 让我们可以直接用
在测试集上。
●StandardScaler .fit_transform(): 将数据调整到所需要的形式。
StandardScaler对象会存储数据变化的变量, 这样我们可以把数据解正规
化到原先的格式。
●cross_validation.train_test_split: 该方法能够将数据集分割成训练
集和测试集。 我们只需要提供两者的比例, 该方法能够自动帮我们处
理
书籍推荐
了解tensorflow基础对象——《面向机器智能的tensorflow实践》
进阶操作tensor对象——《Tensorflow机器学习项目实战》
Hello TensorFlow
import tensorflow as tf如果报错dtype…可以降低numpy的版本(从1.16->1.17)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import tensorflow as tfimport numpy as npimport matplotlib.pyplot as plt% matplotlib inline a=tf.random_normal([2 ,20 ]) sess=tf.Session() out=sess.run(a) x,y=out plt.scatter(x,y) plt. show() ''' %matplotlib inline 这是一条专门的命令,用于通知笔记本将matplotib图表直接显示在浏览器中。 下面逐行分析其余代码,如果你不理解某些术语,请不必担心,后面章节还会一一进行讲解: 1)用TensorFlow定义一个由随机数构成的2×20的矩阵,并将其赋给变量a。 2)启动TensorFlow Session,并将其赋予一个ses对象。 3)用sess.run()方法执行对象a,并将输出(NumPy数组)赋给ot。 4)将这个2×20的矩阵划分为两个1×10的向量x和y。 5)利用pyplot模块绘制散点图,x对应横轴,y对应纵轴。 '''
sess=tf.Session()
Session对象在运行时负责对数据流图进行监督,并且是运行数据流图的主要接口。在本练习之后,我们还将对Session对象进行更为深入的探讨,但现在只需了解在TensorFow中,如果希望运行自己的代码,必须定义一个Session对象。上述代码将Session对象赋给了变量sess,以便后期能够对其进行访问。
target指定了所要使用的执行引擎。对于大多数应用,该参数取为默认的空字符串。在分布式设置中使用Session对象时,该参数用于连接不同的tftrain Server实例(本书后续章节将对此进行介绍)。
graph参数指定了将要在Session对象中加载的Graph对象,其默认值为None,表示将使用当前默认数据流图。当使用多个数据流图时,最好的方式是显式传入你希望运行的Graph对象(而非在一个with语句块内创建Session对象)。
config参数允许用户指定配置Session对象所需的选项,如限制CPU或GPU的使用数目,为数据流图设置优化参数及日志选项等。
Sesionnn()方法接收一个参数fetches ,以及其他三个可选参数:feed_dict 、options和rnn_metadata。本书不打算对options和run_metadata进行介绍,因为它们尚处在实验阶段(因此以后很可能会有变动),且目前用途非常有限,但理解ed_dict非常重要,下文将对其进行讲解。
1.fetches参数
fetches参数接收任意的数据流图元素(Op或Tensor对象),后者指定了用户希望执行的对象。如果请求对象为Tensor对象,则rnun()的输出将为一NumPy数组:如果请求对象为一个Op,则输出将为None。
除了利用fetches获取Tensor对象输出外,还将看到这样的例子:有时也会赋予ftches一个指向某个Op的句柄,这是在运行中的一种有价值的用法。
tf.initialize_all_variables()使是一个这样的例子,它会准备将要使用的所有TensorFow Variable对象(本章稍后将介绍Variable对象)。我们仍然将该Op传给etches参数,但Session.run()的结果将为None:
1 执行初始化Variable对象所需的计算,但返回值为None sess.run(tf.initialize_all_variables())
2.feed_dict参数
参数feed_dict用于覆盖数据流图中的Tensor对象值,它需要Python字典对象作为输入。字典中的“键”为指向应当被覆盖的Tensor对象的句柄,而字典的“值”可以是数字、字符串、列表或NumPy数组(之前介绍过)。这些“值”的类型必须与Tensor的“键”相同,或能够转换为相同的类型。下面通过一些代码来展示如何利用feed_dict重写之前的数据流图中a的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 inport tensorflow as tf a=tf.add(2 ,5 ) b=tf.mul(a,3 ) sess=tf.Session() replace_dict={a:15 } sess.run(b,feed_dict=replace_dict) ''' 请注意,即便a的计算结果通常为7,我们传给eeddict的字典也会将它替换为15。在相当多的场合中,fed_dict都极为有用。由于张量的值是预先提供的,数据流图不再需要对该张量的任何普通依赖节点进行计算。这意味着如果有一个规模较大的数据流图,并希望用一些虚构的值对某些部分进行测试,TensorFlow将不会在不必要的计算上浪费时间。对于指定输入值,eed_dict也十分有用,在稍后的占位符一节中我们将对此进行介绍。 '''
tf.placehold
之前定义的数据流图并未使用真正的“输入”,它总是使用相同的数值5和3。我们真正希望做的是从客户那里接收输入值,这样便可对数据流图中所描述的变换
以各种不同类型的数值进行复用,借助“占位符”可达到这个目的。正如其名称所预示的那样,占位符的行为与Tesor对象一致,但在创建时无须为它们指定具体的数值。它们的作用是为运行时即将到来的某个Tensor对象预留位置,因此实际上变成了“输入”节点。利用tfplaceholderOp可创建占位符:
1 2 3 4 5 6 7 8 9 import tensorflow as tfinport numpy as np a=tf.placeholder(tf.int32,shape=[2 ],name="my_input" ) b=tf.reduce_prod(a,name="prod_b" ) c=tf.reduce_sum(a,name="sum_c" ) d=tf.add(b,c,name="add_d" )
调用tf.placehoder()时,dtype参数是必须指定的,而shape参数可选:
dtype指定了将传给该占位符的值的数据类型。该参数是必须指定的,因为需要确保不出现类型不匹配的错误。
shape指定了所要传入的Tensor对象的形状。请参考前文中对Tensor形状的讨论。shape参数的默认值为None,表示可接收任意形状的Tensor对象。
与任何Op一样,也可在fpaceholer中指定一个name标识符。
为了给占位符传入一个实际的值,需要使用Sesionnm()中的eed_dict参数。我们将指向占位符输出的句柄作为字典(在上述代码中,对应变量a)的“键”,而
将希望传入的Tensor对象作为字典的“值”:
1 2 3 4 5 6 7 8 sess=tf.Session() input_dict={a:np.array([5 ,3 ],dtype=np.int32)} sess.run(d,feed_dict=input_dict)
必须在eed dixt中为待计算的节点的每个依赖占位符包含一个键值对。在上面的代码中,需要计算d的输出,而它依赖于a的输出。如果还定义了一些d不依赖的其他占位符,则无需将它们包含在eed_dict中。
placeholder的值是无法计算的—如果试图将其传入Session.nn(),将引发一个异常。
Variable对象
1.创建Variable对象
Tensor对象和Op对象都是不可变的(immmtable),但机器学习任务的本质决定了需要一种机制保存随时间变化的值。借助TensorFbw中的Varable对象,便可达到这个目的。Variabe对象包含了在对Session.un()多次调用中可持久化的可变张量值。Variabk对象的创建可通过Variabe类的构造方法tVariable()完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 inport tensorflow as tf my_var=tf.Variable(3 ,name="my_variable" ) add=tf.add(5 ,my_var) mul=tf.mul(8 ,my_var) zeros=tf.zeros([2 ,2 ]) ones=tf.ones([6 ]) uniform=tf.random_uniform([3 ,3 ,3 ],minval=0 ,maxval=10 ) normal=tf.random_normal([3 ,3 ,3 ],mean=0.0 ,stddev=2.0 )
除了tfrandom normal()外,经常还会看到人们使用ttrmncated nomal(),因为它不会创建任何偏离均值超过2倍标准差的值 ,从而可以防止有一个或两个元素与该张量中的其他元素显著不同的情况出现:
1 2 3 4 5 trunc=tf.truncated_normal([2 ,2 ],mean=5.0 ,stddev=1.0 ) 可像手工初始化张量那样将这些Op作为Variable对象的初值传入: randon_var=tf.Variable(tf.truncated_normal([2 ,2 ]))
2.Variable对象的初始化
Variable对象与大多数其他TensorFlow对象在Graph中存在的方式都比较类似,但它们的状态实际上是由Session对象管理的。因此,为使用Varinbe对象,需要采取一些额外的步骤—必须在一个Session对象内对Variable对象进行初始化。这样会使Session对象开始追踪这个Variable对象的值的变化。Varabe对象的初始化通常是通过将tinitialize_all_variabkes()Op传给Sessionrun()完成的:
1 2 3 4 5 6 7 8 9 init=tf.initialize_all_variables() sess=tf.Session() sess.run(init) var1=tf.Variable(0 ,name="initialize_me" ) var2=tf.Variable(1 ,name="no_initialization" ) init=tf.initialize_variables([var1],name="init_var1" ) sess=tf.Session() sess.run(init)
3.Variable对象的修改
要修改Variablk对象的值,可使用Variable.assign()方法。该方法的作用是为Variable对象赋予新值。请注意,Variable.assign()是一个Op,要使其生效必须在一个Session对象中运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 my_var=tf.Variable(1 ) my_var_times_two=my_var.assign(my_var*2 ) sess=tf.Session() sess.run(init) sess.run(my_var_times_two) sess.run(my_var_times_two) sess.run(my_var_times_two) 对于Variablk对象的简单自增和自减,TensorFlow提供了Variable.asign add()方法和Variable.assignsub()方法: sess.run(my_var.assign_add(1 )) sess.run(my_var.assign_sub(1 ))
△由于不同Session对象会各自独立地维护Varablk对象的值,因此每个Session对象都拥有自己的、在Graph对象中定义的Variabe对象的当前值:
4.trainable参数
在本书的后续章节将介绍各种能够自动训练机器学习模型的Optinmizer类,这意味着这些类将自动修改Variable对象的值,而无须显式做出请求。在大多数情况下,这与读者的期望一致,但如果要求Graph对象中的一些Variabk对象只可手工修改,而不允许使用Optimizer类时,可在创建这些Variable对象时将其raimbe参数设为False:not_trainable=tf.Variable(0,trainable=False)