目录

  • TensorFlow实现逻辑回归
    • 加载mnist数据集
    • Logistic Regression
    • 定义计算图
      • 关于参数更新在pytorch上的比较
    • 执行计算图
    • 补充:分析计算图
  • 使用高层的封装Keras
    • Keras Sequential
    • 关于正则化
    • 基于Keras Sequential的mnist分类
  • 继承Keras Model
    • 准备工作
    • tf.data.Dataset.from_tensor_slices数据加载
    • Keras Model继承
      • tensorflow1.x适用
      • tensorflow2.0 Beta 适用

TensorFlow实现逻辑回归

加载mnist数据集

为了简单起见,使用小型而经典的mnist数据集,在tensorflow中,已有处理mnist数据集的内置工具:tensorflow.examples.tutorials.mnist
数据集mnist的下载链接为:mnist
下载完成后,在本地mnist目录下有以下4个压缩文件:

利用tensorflow的工具加载数据集:

from tensorflow.examples.tutorials.mnist import input_datamnist=input_data.read_data_sets("./mnist",one_hot=True)print(mnist.train.images.shape)
print(mnist.train.labels.shape)
"""
(55000, 784)
(55000, 10)
"""

数据集中,images中每个图像已经是归一化处理的张量,且张量(1,28,28)(1,28,28)(1,28,28)已经被reshape到(784,)(784,)(784,),其类别的形状为(10,)(10,)(10,):

import matplotlib.pyplot as pltplt.imshow(mnist.train.images[6].reshape([28,28]))
plt.show()print(mnist.train.labels[6])print(mnist.train.images[6].shape)
print(mnist.train.labels[6].shape)


由于归一化处理的原因,显示的图像不是纯黑白的;

Logistic Regression

逻辑回归的分类原理来自sigmoid函数,如果对一个样本,输入nnn维特征向量为X=[x1,x2,...,xn]TX=[x_{1},x_{2},...,x_{n}]^{T}X=[x1​,x2​,...,xn​]T,则利用逻辑回归二分类的模型为:
logistic(X)=11+e−(WX+b)logistic(X)=\frac{1}{1+e^{-(WX+b)}}logistic(X)=1+e−(WX+b)1​
WWW和bbb是模型的待学习参数;
广义地,如果面对多类别问题,假设共CCC类,其实可以用softmax代替sigmoid,对于第iii类对象,分类概率计算为:
z=WX+bz=WX+bz=WX+b
softmax(z)=exp(z[i])∑j=0C−1exp(z[j])softmax(z)=\frac{exp(z[i])}{\sum_{j=0}^{C-1}exp(z[j])}softmax(z)=∑j=0C−1​exp(z[j])exp(z[i])​

定义计算图

首先,设置超参数与定义占位符:

import tensorflow as tf
# Model Init
batch_size=200
lr=1e-1
num_epochs=50num_train,num_feats=mnist.train.images.shape
num_classes=mnist.train.labels.shape[1]num_test=mnist.test.images.shape[0]train_x=tf.placeholder(tf.float32,[None,num_feats],name="train_x")
train_y=tf.placeholder(tf.float32,[None,num_classes],name="train_y")

定义待学习参数:

w=tf.Variable(tf.random_normal(shape=[num_feats,num_classes],stddev=0.1),name="weights")
b=tf.Variable(tf.zeros([num_classes]),name="bias")

定义模型,并计算交叉熵损失函数:

# Model : softmax(Wx+b)
logits=tf.add(tf.matmul(train_x,w,name="matdot"),b,name="Add")cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=logits,labels=train_y,name="loss")

函数softmax_cross_entropy_with_logits先根据输入logits的得分计算softmax概率,再结合labels计算交叉熵,labels为one-hot编码的向量,tensorflow不同于pytorch的索引取值,tensorflow必须直观地传递one-hot编码向量;


tensorflow.nn.softmax_cross_entropy_with_logits(logits, labels, axis=-1, name=None)

axis=-1代表在输入张量最后一个轴方向进行操作,在这个实验中,输入张量logits为(None,10)(None,10)(None,10),每个样本计算softmax后就变成了一组概率值(10,)(10,)(10,),交叉熵结合标签对真实类别的概率值取对数并取相反数,得到一个数值,所以cross_entropy形状为(None,)(None,)(None,)


基于每个样本的交叉熵计算损失:

# 如果不指定axis,则计算所有元素的均值
loss=tf.reduce_mean(cross_entropy,name="reduce_mean_cross_entropy")

计算模型的分类准确率:

preds=tf.nn.softmax(logits,name="softmax") # [None,10]# tf.equal返回和输入两张量形状相同的布尔型张量
correct_preds=tf.equal(tf.argmax(preds,1,name="preds_arg"),tf.argmax(train_y,1,name="label_arg"),name="equal")# tf.cast 数据类型转换
accuracy=tf.reduce_mean(tf.cast(correct_preds,tf.float32),name="reduce_mean_correct")

用梯度下降优化模型:

optimizer=tf.train.GradientDescentOptimizer(lr,name="GradientDescent").minimize(loss,name="minimize")

optimizer实际上是一个计算图,依赖于子计算图:loss和源op:lr;
定义其他对象:

import timenum_batches=num_train/batch_size
losses=[]
train_accs,valid_accs=[],[]
time_start=time.time()

关于参数更新在pytorch上的比较

  • pytorch中,从torch.optim选择优化方法,并将model.parameters()作为参数传入,其本质也是类似上面创建了新的计算图,执行optimizer.step()后就根据张量自身的对象grad,按照优化算法的流程更新parameters()
  • tensorflow的张量没有对象grad,所以在会话执行optimizer时,会调用gradients()计算梯度,再更新计算图中的Variable对象;
  • tensorflow的张量自身不设置对象grad,这避免了grad的累加,从而不需要pytorch中的model.zero_grad()操作;

执行计算图

参数更新已在上面进行了分析;所以,只需要把optimizer加入到会话,运行这个计算图,便可以实现训练:

with tf.Session() as sess:writer=tf.summary.FileWriter("./LRGraphs",sess.graph)# 初始化模型的参数sess.run(tf.global_variables_initializer())for i in range(num_epochs):total_loss=0.0for _ in range(int(num_batches)):x_batch,y_batch=mnist.train.next_batch(batch_size)_,loss_batch=sess.run([optimizer,loss],feed_dict={train_x:x_batch,train_y:y_batch})total_loss += loss_batchtrain_acc = sess.run([accuracy], feed_dict={train_x: mnist.train.images, train_y: mnist.train.labels})valid_acc = sess.run([accuracy],feed_dict={train_x: mnist.validation.images, train_y: mnist.validation.labels})losses.append(total_loss/num_batches)train_accs.append(train_acc)valid_accs.append(valid_acc)print("Number of iteration: {}, total_loss = {}, train accuracy = {}, validation accuracy = {}".format(i, total_loss/num_batches, train_acc, valid_acc))test_acc = sess.run([accuracy], feed_dict={train_x: mnist.test.images, train_y: mnist.test.labels})time_end = time.time()print("Time used for training = {} seconds.".format(time_end - time_start))print("MNIST image classification accuracy on test set = {}".format(test_acc))writer.close()

绘制学习曲线:

# Plot the losses during training.
plt.figure()
plt.title("Logistic regression with TensorFlow")
plt.plot(losses, "b-o", linewidth=2)
plt.grid(True)
plt.xlabel("Iteration")
plt.ylabel("Cross-entropy")
plt.show()

补充:分析计算图

使用tensorboard查看计算图,可以得到:

左边的计算图表示需要计算梯度的op,右边计算图表示如何执行minimize这个op,minimize就是优化模型的过程,所以需要weightsbias以及更新它们的gridents

容易看出,执行optimizer时,原计算图自动添加并执行了gradients(),左边分支为reduce_mean_cross_entropy用于计算loss,右边分支为reduce_mean_correct用于计算accuracy,weightsbias在执行gradients()的同时也执行了minimize

使用高层的封装Keras

Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow,CNTK,或者 Theano 作为后端运行。Keras 的开发重点是支持快速的实验。能够以最小的时延把你的想法转换为实验结果,是做好研究的关键。
深度学习发展到现在,Keras已经融入了TensorFlow,使用Keras类似于使用pytorch中的nn库,让研究人员用搭建积木的方式实现模型。

Keras Sequential

首先以Dense(类似torch.nn.Linear)为例了解其使用:

keras.layers.Dense(units,activation=None,input_shape=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None)
  • units: 正整数,输出空间维度
  • activation:激活函数
  • input_shape:输入张量去除batch_size维度后的形状
  • kernel_initializer:权值矩阵的初始化方法
  • kernel_regularizer:权值矩阵的正则化方法

关于正则化

关于正则化:
正则化允许在优化过程中对层的参数进行惩罚,把待学习参数www与惩罚系数aaa融入损失函数JJJ中;

  • L1正则化后损失函数为:
    J=J+a∣w∣J=J+a|w|J=J+a∣w∣
  • L2正则化后损失函数为:
    J=J+aw2J=J+aw^{2}J=J+aw2

可见,惩罚项加入损失,迫使参数值减小,而对于一个线性层z=WX+bz=WX+bz=WX+b来说,其输出zzz的绝对值将减小,如果让其通过sigmoid函数,值小的zzz更容易落入激活函数的线性区间,网络捕捉线性分布是容易的,模型不易于复杂化,也就避免了过拟合。
Keras有已经定义好的正则化方法:

keras.regularizers.l1(0.)
keras.regularizers.l2(0.)
keras.regularizers.l1_l2(l1=0.01, l2=0.01)# 使用
Dense(kernel_regularizer=regularizers.l2(0.01))

也可以自己定义:

from keras import backend as Kdef l1_reg(weight_matrix):return 0.01 * K.sum(K.abs(weight_matrix))# 使用
Dense(kernel_regularizer=l1_reg)

基于Keras Sequential的mnist分类

因为keras封装了tensorflow,所以不需要显式地执行计算图,keras符合研究人员的习惯:定义模型,指定优化方法与损失函数,训练,验证;
同样使用本篇第一部分的mnist数据集,使用Keras Sequential定义模型为:

model=tf.keras.models.Sequential([tf.keras.layers.Dense(128,activation="relu",input_shape=(784,) # 输入张量为(None,784)),tf.keras.layers.Dropout(0.2),tf.keras.layers.Dense(10,activation="softmax",input_shape=(128,) #可以省略)]
)# 打印模型结构
model.summary()

model.summary()可以打印模型结构:

指定优化方法与损失函数通过compile实现:

model.compile(optimizer="adam",loss="categorical_crossentropy",metrics=['accuracy'])

训练模型:

x_train=mnist.train.images
y_train=mnist.train.labelsmodel.fit(x_train, y_train, epochs=5)

验证:

x_test=mnist.validation.images
y_test=mnist.validation.labelsmodel.evaluate(x_test,y_test)

继承Keras Model

准备工作

首先导入需要的包和模块;
注意,由于后面会使用生成器方式:tf.data.Dataset.from_tensor_slices加载数据,在tensorflow1.x版本中,dataset.__iter__()仅支持在eager execution 为 enabled 的情况下可调用,所以要执行tf.enable_eager_execution()

import tensorflow as tffrom tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Modeltf.enable_eager_execution()

加载mnist数据集:

from tensorflow.examples.tutorials.mnist import input_datamnist=input_data.read_data_sets("./mnist",one_hot=True)print(mnist.train.images.shape) # (55000, 784)
print(mnist.train.labels.shape) # (55000, 10)

由于要对图像进行卷积,所以要改变数据的形状,使之成为单通道的图像张量;


tf.expand_dims可以增加input张量维度,axis为新增维度的轴序号;

tf.expand_dims(input,axis=None,name=None
)x=tf.zeros([5,3])
# -1表示新增维度在最后一维
x=tf.expand_dims(x,axis=-1)
"""
<tf.Tensor 'ExpandDims:0' shape=(5, 3, 1) dtype=float32>
"""

改变张量为:

x_train=mnist.train.images.reshape(-1,28,28)
y_train=mnist.train.labelsx_test=mnist.validation.images.reshape(-1,28,28)
y_test=mnist.validation.labels# 由于要使用卷积Conv2D,所以增加一个通道
x_train=tf.expand_dims(x_train,axis=-1) # (55000, 28, 28, 1)
x_test=expand_dims(x_test,axis=-1) # (5000, 28, 28, 1)

tf.data.Dataset.from_tensor_slices数据加载

本质是基于生成器加载数据,类似于pytorch中的dataloader;
在使用前需要先知道shuffle与batch的机制:

  • 对于shuffle(buffer_size),参数buffer_size值越大,意味着数据混乱程度也越大;
    假设buffer_size = 9,也即先从数据集中取出 9 个batch到 buffer 中,真正训练数据的样本将从 buffer 中获取。 从 buffer 随机取出一个batch即 “item7”,现在 buffer 内只有 8 个batch,然后从数据集中按顺序取出batch即 “item10” 到 buffer 区域填补空缺;
  • batch(batch_size)即为设置batch的数据数量;
  • 如果没有shuffle,则根据batch顺序加载数据;

因此,返回一个dataloader有:

train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(32)test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)

获取一个batch:

batch=next(iter(train_ds))print(batch[0].shape) # (32, 28, 28, 1)
print(batch[1].shape) # (32, 10)

Keras Model继承

和pytorch中继承torch.nn.Module是相似的,继承tf.keras.Model至少需要实现两个实例方法:

  • 1.要求导的层需要定义在__init__下
  • 2.层的前向传播过程写在call下

Conv2D,Flatten,Input
Conv2D:

keras.layers.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None)
  • filters:输出张量的通道数
  • data_format:默认为channels_last;
    如果data_format='channels_first',则输入输出张量格式为(batch,channel,height,width)(batch,channel,height,width)(batch,channel,height,width),否则默认为(batch,height,width,channel)(batch,height,width,channel)(batch,height,width,channel)

Flatten:

keras.layers.Flatten(data_format=None)
  • data_format:默认为channels_last;

将输入张量reshape为一个向量,但batch维度不变,即(batch,height,width,channel)(batch,height,width,channel)(batch,height,width,channel)变为(batch,height×width×channel)(batch,height\times width\times channel)(batch,height×width×channel)

Input:
用于初始化一个张量实例

tf.keras.layers.Input(shape=None,batch_size=None,name=None,dtype=None
)

shape不包含batch维度;
比如:

x=tf.keras.layers.Input(shape=(28,28,1),batch_size=32)
"""
<tf.Tensor 'input:0' shape=(32, 28, 28, 1) dtype=float32>
"""

定义模型:

class MyModel(Model):def __init__(self):super().__init__()self.conv1=Conv2D(32,3,activation="relu")self.flatten=Flatten()self.d1=Dense(128,activation="relu")self.d2=Dense(10,activation="softmax")def call(self,x):x=self.conv1(x)x=self.flatten(x)x=self.d1(x)return self.d2(x) # (None,10)model=MyModel()

剩下部分与版本相关,个人认为版本问题的确是tensorflow的大问题

tensorflow1.x适用

简单调用fit与evaluate,注意必须compile模型:

model.compile(optimizer="adam",loss="categorical_crossentropy",metrics=['accuracy'])

训练与验证,注意,fit和evaluate需要输入ndarray类型的数据:

NUM_EPOCHS=5for epoch in range(NUM_EPOCHS):for idx,(images,labels) in enumerate(train_ds):# 虽然写了epochs=1,实际上是一个batch作为此次fit的epoch# fit和evaluate需要输入ndarray类型的数据model.fit(images.numpy(),labels.numpy(),epochs=1)for idx,(t_images,t_labels) in enumerate(test_ds):# 分别在不同batch上验证model.evaluate(t_images.numpy(),t_labels.numpy())

tensorflow2.0 Beta 适用

在tensorflow2.0 Beta中,Google工程师完成了2.0 API的重命名和弃用符号,意味着这将是2.0最终版本的API,不用担心使用2.0 API 编写的代码在将来不可用;


Alpha 指的是内测,即现在说的 CB,即开发团队内部测试的版本或者有限用户的体验测试版本。Beta 指的是公测,即针对所有用户公开的测试版本。而做过一些修改,成为正式发布的候选版本时(现在叫做 RC - Release Candidate),叫做 Gamma;


安装tensorflow2.0 Beta:

pip install tensorflow-gpu==2.0.0-beta0

选择损失函数与优化方法:

loss_object = tf.keras.losses.CategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam()

选择衡量指标来度量模型的损失(loss)和准确率(accuracy),这些指标在调用时累积值,使用.result()可以返回结果:

train_loss = tf.keras.metrics.Mean()
train_accuracy = tf.keras.metrics.CategoricalAccuracy()test_loss = tf.keras.metrics.Mean()
test_accuracy = tf.keras.metrics.CategoricalAccuracy()

使用 tf.GradientTape 来训练模型:

def train_step(images, labels):with tf.GradientTape() as tape:preds=model.call(images)loss=loss_object(labels,preds)# 计算梯度gradients=tape.gradient(loss,model.trainable_variables)# 更新参数optimizer.apply_gradients(zip(gradients,model.trainable_variables))# 计算评价指标train_loss(loss)train_accuracy(labels,preds)

验证模型:

def test_step(images,labels):preds=model.call(images)t_loss=loss_object(labels,preds)# 计算评价指标test_loss(t_loss)test_accuracy(labels,preds)

加载数据训练模型并验证:

NUM_EPOCHS=5for epoch in range(NUM_EPOCHS):# 在每一个epoch开始时,重置评估指标train_loss.reset_states()train_accuracy.reset_states()test_loss.reset_states()test_accuracy.reset_states()for idx,(images,labels) in enumerate(train_ds):train_step(images,labels)for idx,(t_images,t_labels) in enumerate(test_ds):test_step(t_images,t_labels)template="Epoch {},Loss:{},Accuracy:{},Test Loss:{},Test Accuracy:{}"print(template.format(epoch+1,train_loss.result(),train_accuracy.result(),test_loss.result(),test_accuracy.result()))

结果为:

Epoch 1, Loss: 0.13825324177742004, Accuracy: 95.89166259765625, Test Loss: 0.07461485266685486, Test Accuracy: 97.47999572753906
Epoch 2, Loss: 0.04554400220513344, Accuracy: 98.61666870117188, Test Loss: 0.05126383528113365, Test Accuracy: 98.29000091552734
Epoch 3, Loss: 0.024927066639065742, Accuracy: 99.18500518798828, Test Loss: 0.05301696062088013, Test Accuracy: 98.30999755859375
Epoch 4, Loss: 0.014068767428398132, Accuracy: 99.52832794189453, Test Loss: 0.051672786474227905, Test Accuracy: 98.58000183105469
Epoch 5, Loss: 0.009344187565147877, Accuracy: 99.69166564941406, Test Loss: 0.06102905049920082, Test Accuracy: 98.25

附录6:TensorFlow基础(二)相关推荐

  1. [Python人工智能] 二.TensorFlow基础及一元直线预测案例

    从本篇文章开始,作者正式开始研究Python深度学习.神经网络及人工智能相关知识.前一篇文章讲解了TensorFlow的安装过程和神经网络基础概念.这篇文章将分享TensorFlow基础并介绍一元直线 ...

  2. 深度学习(6)TensorFlow基础操作二: 创建Tensor

    深度学习(6)TensorFlow基础操作二: 创建Tensor 一. 创建方式 1. From Numpy,List 2. zeros,ones (1) tf.zeros() (2) tf.zero ...

  3. TensorFlow基础剖析

    TensorFlow基础剖析 一.概述 TensorFlow 是一个使用数据流图 (Dataflow Graph) 表达数值计算的开源软件库.它使用节点表示抽象的数学计算,并使用 OP 表达计算的逻辑 ...

  4. 【AI实战】快速掌握TensorFlow(二):计算图、会话

    2019独角兽企业重金招聘Python工程师标准>>> 在前面的文章中,我们已经完成了AI基础环境的搭建(见文章:Ubuntu + Anaconda + TensorFlow + G ...

  5. [Python人工智能] 三.TensorFlow基础之Session、变量、传入值和激励函数

    从本篇文章开始,作者正式开始研究Python深度学习.神经网络及人工智能相关知识.前一篇文章讲解了TensorFlow基础和一元直线预测的案例:本篇文章将详细介绍Session.变量.传入值和激励函数 ...

  6. 深度学习(11)TensorFlow基础操作七: 向前传播(张量)实战

    深度学习(11)TensorFlow基础操作七: 向前传播(张量)实战 1. 导包 2. 加载数据集 3. 转换数据类型 4. 查看x.shape, y.shape, x.dtype, y.dtype ...

  7. 深度学习(7)TensorFlow基础操作三: 索引与切片

    深度学习(7)TensorFlow基础操作三: 索引与切片 一. 基础索引 1. Basic indexing 2. Numpy-style indexing 3. start : end 4. 切片 ...

  8. 机器学习Tensorflow基础知识、张量与变量

    TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组, ...

  9. Tensorflow基础语法和概念

    Tensorflow基础语法和概念 一些说明:学习tensorflow用到的Python语法,请参考这篇博客 计算图模型 Tensorflow的构建的机器学习模型都是有向图模型,在Tensorflow ...

最新文章

  1. 在同一个文件中定义多个命名空间
  2. JMeter学习笔记--JMeter常用测试元件
  3. POJ-2746:约瑟夫问题(Java版)
  4. 中国移动携手腾讯开展5G联合创新
  5. 开始使用gradle
  6. rbac 权限分配, 基于formset实现,批量增加
  7. php socket 心跳机制,socket学习纪录2: workerman 心跳功能实现
  8. angular HttpClient getbyid 方法获取数据
  9. 双目摄像头和单目摄像头_挑战激光雷达,MAXIEYE要重新定义单目摄像头?
  10. NUMA与英特尔下一代Xeon处理器学习心得(5)
  11. Error in cor(xdata) : 'x'必需为数值
  12. 智能颈部按摩仪设计——2.开发环境搭建
  13. query相关搜索词推荐
  14. android字符串+数字变量方法之%1$s、%1$d的用法
  15. 8种CSS3按钮动画特效【附源码】
  16. ES7之async、await
  17. ubuntu赋予当前用户root权限
  18. Linux配置本地yum源
  19. QQ音乐客户端Web页面通用性能优化实践
  20. DDR,DDR2,DDR3,SDRAM比较区别

热门文章

  1. 从零到一编码实现Redis分布式锁
  2. 这款笔记本写代码真爽,包邮送一台!
  3. 很遗憾,我们正在逐渐丧失专注阅读的能力
  4. 吊打MySQL,MariaDB到底强在哪?
  5. 当打开淘宝的那一刻,它就知道你想要的是什么
  6. 编程入门到进大厂,你需要这套学习架构
  7. 有赞分层自动化测试实践
  8. 敏捷和DevOps:是敌是友?
  9. 轻雀世界知名体育用品零售商D的交流与思考
  10. leangoo大讲堂:scrum敏捷开发实战——深圳站