一、计算图中的操作

在这个例子中,我们将结合前面所学的知识,传入一个列表到计算图中的操作,并打印返回值:

声明张量和占位符。这里,创建一个numpy数组,传入计算图操作:

import tensorflow as tf
import numpy as np # Create graph
sess = tf.Session()
# Create data to feed in
x_vals = np.array([1., 3., 5., 7., 9.])
x_data = tf.placeholder(tf.float32)
m = tf.constant(3.)
# Multiplication
prod = tf.multiply(x_data, m)
for x_val in x_vals:
print(sess.run(prod, feed_dict={x_data: x_val}))

输出:

3.0
9.0
15.0
21.0
27.0

在下面这个例子中,我们将学习如何在同一个计算图中进行多个乘法操作。

下面我们将用两个矩阵乘以占位符,然后做加法。传入两个矩阵(三维numpy数组):

我们将传入两个形状为3×5的numpy数组,然后
每个矩阵乘以常量矩阵(形状为:5×1),将返回一个形状为3×1的矩阵。紧接着再乘以1×1的矩阵,返回的
结果矩阵仍然为3×1。最后,加上一个3×1的矩阵,示例如下:

1.首先,创建数据和占位符:

# Create graph
sess = tf.Session()
# Create data to feed in
my_array = np.array([[1., 3., 5., 7., 9.],
[-2., 0., 2., 4., 6.],
[-6., -3., 0., 3., 6.]])
x_vals = np.array([my_array, my_array + 1])
x_data = tf.placeholder(tf.float32, shape=(3, 5))

2.接着,创建矩阵乘法和加法中要用到的常量矩阵:

m1 = tf.constant([[1.],[0.],[-1.],[2.],[4.]])
m2 = tf.constant([[2.]])
a1 = tf.constant([[10.]])

3.现在声明操作,表示成计算图:

# 1st Operation Layer = Multiplication
prod1 = tf.matmul(x_data, m1) # 2nd Operation Layer = Multiplication
prod2 = tf.matmul(prod1, m2) # 3rd Operation Layer = Addition
add1 = tf.add(prod2, a1)

4.最后,通过计算图赋值:

for x_val in x_vals:
print(sess.run(add1, feed_dict={x_data: x_val}))

输出:

[[102.]
[ 66.]
[ 58.]]
[[114.]
[ 78.]
[ 70.]]

在我们通过计算图运行数据之前心里要有个数:声明数据形状,预估操作返回值形状。由于预先不知道
或者维度在变化,情况也可能发生变化。为了实现目标,我们指明变化的维度,或者事先不知道的维度设为
none。例如,占位符有未知列维度,使用方式如下:

x_data = tf.placeholder(tf.float32,shape=(3,None))

二、TensorFlow的多层Layer

1.首先,通过numpy创建2D图像,4×4像素图片。我们将创建成四维:第一维和最后一维大小为1。注
意,TensorFlow的图像函数是处理四维图片的,这四维是:图片数量、高度、宽度和颜色通道。这里是一张
图片,单颜色通道,所以设两个维度值为1:

# Create graph
sess = tf.Session() # Create a small random 'image' of size 4x4
x_shape = [1, 4, 4, 1]
x_val = np.random.uniform(size=x_shape)

2.下面在计算图中创建占位符。此例中占位符是用来传入图片的,代码如下:

x_data = tf.placeholder(tf.float32, shape=x_shape)

3.为了创建过滤4×4像素图片的滑动窗口,我们将用TensorFlow内建函数conv2d()(常用来做图像处
理)卷积2×2形状的常量窗口。conv2d()函数传入滑动窗口、过滤器和步长。本例将在滑动窗口四个方向
上计算,所以在四个方向上都要指定步长。创建一个2×2的窗口,每个方向长度为2的步长。为了计算平均
值,我们将用常量为0.25的向量与2×2的窗口卷积,代码如下:

my_filter = tf.constant(0.25, shape=[2, 2, 1, 1])
my_strides = [1, 2, 2, 1]
mov_avg_layer = tf.nn.conv2d(x_data, my_filter, my_strides,
padding='SAME', name='Moving_Avg_Window')

4.注意,我们通过conv2d()函数的name参数,把这层Layer命名为“Moving_Avg_Window”。

5.现在定义一个自定义Layer,操作滑动窗口平均的2×2的返回值。自定义函数将输入张量乘以一个2×2
的矩阵张量,然后每个元素加1。因为矩阵乘法只计算二维矩阵,所以剪裁图像的多余维度(大小为1)。
TensorFlow通过内建函数squeeze()剪裁。下面是新定义的Layer:

def custom_layer(input_matrix):
input_matrix_sqeezed = tf.squeeze(input_matrix)
A = tf.constant([[1., 2.], [-1., 3.]])
b = tf.constant(1., shape=[2, 2])
temp1 = tf.matmul(A, input_matrix_sqeezed)
temp = tf.add(temp1, b) # Ax + b
return(tf.sigmoid(temp))

6.现在把刚刚新定义的Layer加入到计算图中,并且用tf.name_scope()命名唯一的Layer名字,后续在
计算图中可折叠/扩展Custom_Layer层,代码如下:

# Add custom layer to graph
with tf.name_scope('Custom_Layer') as scope:
custom_layer1 = custom_layer(mov_avg_layer)

7.为占位符传入4×4像素图片,然后执行计算图,代码如下:

print(sess.run(custom_layer1, feed_dict={x_data: x_val}))

输出:

[[0.9027293  0.9333066 ]
[0.84296674 0.8839635 ]]

三、TensorFlow实现损失函数

损失函数(loss function)对机器学习来讲是非常重要的。它们度量模型输出值与目标值(target)间的
差值。本节会介绍TensorFlow中实现的各种损失函数。

为了优化机器学习算法,我们需要评估机器学习模型训练输出结果。在TensorFlow中评估输出结果依赖
损失函数。损失函数告诉TensorFlow,预测结果相比期望的结果是好是坏。在大部分场景下,我们会有算法
模型训练的样本数据集和目标值。损失函数比较预测值与目标值,并给出两者之间的数值化的差值。

为了比较不同损失函数的区别,我们将会在图表中绘制出来。先创建计算图,然后加载
matplotlib(Python的绘图库),代码如下:

import matplotlib.pyplot as plt
import tensorflow as tf

首先,将讲解回归算法的损失函数。回归算法是预测连续因变量的。创建预测序列和目标序列作为张
量,预测序列是-1到1之间的等差数列,代码如下:

# Numerical Predictions
x_vals = tf.linspace(-1., 1., 500)
target = tf.constant(0.)

1.回归模型的损失函数

(1)L2正则损失函数(即欧拉损失函数)。L2正则损失函数是预测值与目标值差值的平方和。注意,上述
例子中目标值为0。L2正则损失函数是非常有用的损失函数,因为它在目标值附近有更好的曲度,机器学习
算法利用这点收敛,并且离目标越近收敛越慢,代码如下:

# L2 loss
# L = (pred - actual)^2
l2_y_vals = tf.square(target - x_vals)
l2_y_out = sess.run(l2_y_vals)

注意:

TensorFlow有内建的L2正则形式,称为nn.l2_loss()。这个函数其实是实际L2正则
的一半,换句话说,它是上面l2_y_vals的1/2。

(2)L1正则损失函数(即绝对值损失函数)。与L2正则损失函数对差值求平方不同的是,L1正则损失函数
对差值求绝对值。L1正则在目标值附近不平滑,这会导致算法不能很好地收敛。代码如下:

# L1 loss
# L = abs(pred - actual)
l1_y_vals = tf.abs(target - x_vals)
l1_y_out = sess.run(l1_y_vals)

(3)Pseudo-Huber 损失函数

Pseudo-Huber损失函数是Huber损失函数的连续、平滑估计,试图利用L1和L2正则削减极值处的陡峭,
使得目标值附近连续。它的表达式依赖参数delta。我们将绘图来显示delta1=0.25和delta2=5的区别

Huber损失函数经常用于回归问题,它是分段函数,公式如下:

从这个公式可以看出当残差(预测值与目标值的差值,即y-f(x) )很小的时候,损失函数为L2范数,残差大的时候,为L1范数的线性函数。

Peseudo-Huber损失函数是Huber损失函数的连续、平滑估计,在目标附近连续,公式如下:

该公式依赖于参数delta,delta越大,则两边的线性部分越陡峭。

# Pseudo-Huber loss
# L = delta^2 * (sqrt(1 + ((pred - actual)/delta)^2) - 1)
delta1 = tf.constant(0.25)
phuber1_y_vals = tf.multiply(tf.square(delta1), tf.sqrt(1. + tf.square((target - x_vals) / delta1)) - 1.)
phuber1_y_out = sess.run(phuber1_y_vals) delta2 = tf.constant(5.)
phuber2_y_vals = tf.mul(tf.square(delta2), tf.sqrt(1. + tf.square((target - x_vals) / delta2)) - 1.)
phuber2_y_out = sess.run(phuber2_y_vals)

以下为L1、L2、Huber损失函数的对比图如下,其中Huber的delta取0.25、5两个值:

x_array = sess.run(x_vals)
plt.plot(x_array, l2_y_out, 'b-', label='L2 Loss')
plt.plot(x_array, l1_y_out, 'r--', label='L1 Loss')
plt.plot(x_array, phuber1_y_out, 'k-.', label='P-Huber Loss(0.25)')
plt.plot(x_array, phuber2_y_out, 'g:', label='P-Huber Loss(5.)')
plt.ylim(-0.2, 0.4)
plt.legend(loc='lower right', prop={'size': 11})
plt.show()

2.分类模型的损失函数

分类损失函数主要用于评估预测分类结果,重新定义预测值(-3至5的等差序列)和目标值(目标值为1),如下:

y_pred=tf.linspace(-3., 5., 100)

y_target=tf.constant(1.)

y_targets=tf.fill([100, ], 1.)

(1)Hinge损失函数

Hinge损失常用于二分类问题,主要用来评估向量机算法,但有时也用来评估神经网络算法,公式如下:

loss_hinge_vals = tf.maximum(0., 1. – tf.mul(y_target, y_pred))

loss_hinge_out = sess.run(loss_hinge_vals)

(2)两类交叉熵(Cross-entropy)损失函数

交叉熵来自于信息论,是分类问题中使用广泛的损失函数。交叉熵刻画了两个概率分布之间的距离,当两个概率分布越接近时,它们的交叉熵也就越小,给定两个概率分布p和q,则距离如下:

对于两类问题,当一个概率p=y,则另一个概率q=1-y,因此代入化简后的公式如下:

# Cross entropy loss
# L = -actual * (log(pred)) - (1-actual)(log(1-pred))
xentropy_y_vals = - tf.multiply(target, tf.log(x_vals)) - tf.multiply((1. - target), tf.log(1. - x_vals))
xentropy_y_out = sess.run(xentropy_y_vals)

(3)Sigmoid交叉熵损失函数

与上面的两类交叉熵类似,只是将预测值y_pred值通过sigmoid函数进行转换,再计算交叉熵损失。

# Sigmoid entropy loss
# L = -actual * (log(sigmoid(pred))) - (1-actual)(log(1-sigmoid(pred)))
# or
# L = max(actual, 0) - actual * pred + log(1 + exp(-abs(actual)))
xentropy_sigmoid_y_vals = tf.nn.sigmoid_cross_entropy_with_logits(labels=x_vals, logits=targets)
xentropy_sigmoid_y_out = sess.run(xentropy_sigmoid_y_vals)

(4)加权交叉熵损失函数

加权交叉熵损失函数是Sigmoid交叉熵损失函数的加权,是对正目标的加权。假定权重为0.5,在TensorFlow中的调用方式如下:

# Weighted (softmax) cross entropy loss
# L = -actual * (log(pred)) * weights - (1-actual)(log(1-pred))
# or
# L = (1 - pred) * actual + (1 + (weights - 1) * pred) * log(1 + exp(-actual))
weight = tf.constant(0.5)
xentropy_weighted_y_vals = tf.nn.weighted_cross_entropy_with_logits(x_vals, targets, weight)
xentropy_weighted_y_out = sess.run(xentropy_weighted_y_vals)

(5)Softmax交叉熵损失函数

Softmax交叉熵损失函数是作用于非归一化的输出结果,只针对单个目标分类计算损失。

通过softmax函数将输出结果转化成概率分布,从而便于输入到交叉熵里面进行计算(交叉熵要求输入为概率),softmax定义如下:

结合前面的交叉熵定义公式,则Softmax交叉熵损失函数公式如下:

# Softmax entropy loss
# L = -actual * (log(softmax(pred))) - (1-actual)(log(1-softmax(pred)))
unscaled_logits = tf.constant([[1., -3., 10.]])
target_dist = tf.constant([[0.1, 0.02, 0.88]])
softmax_xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=unscaled_logits, logits=target_dist)

用于回归相关的损失函数,对比图如下:

3.总结

下面对各种损失函数进行一个总结,如下表所示:

在实际使用中,对于回归问题经常会使用MSE均方误差(L2取平均)计算损失,对于分类问题经常会使用Sigmoid交叉熵损失函数。

TensorFlow机器学习实战指南之第二章的更多相关文章

  1. TensorFlow机器学习实战指南之第二章2

    TensorFlow实现反向传播 本节先举个简单的回归算法的例子.这里先举一个简单的例子,从均值1,标准差为0.1的正态分布中随机抽样100个数,然后乘以变量A,损失函数L2正则函数,也就是实现函数X ...

  2. TensorFlow机器学习实战指南之第一章

    TensorFlow基础 一.TensorFlow算法的一般流程 1.导入/生成样本数据集 2.转换和归一化数据:一般来讲,输入样本数据集并不符合TensorFlow期望的形状,所以需要转换数据格式以 ...

  3. 学习TF:《TensorFlow机器学习实战指南》中文PDF+英文PDF+代码

    从实战角度系统讲解TensorFlow基本概念及各种应用实践.真实的应用场景和数据,丰富的代码实例,详尽的操作步骤,带你由浅入深系统掌握TensorFlow机器学习算法及其实现. <Tensor ...

  4. HTTP权威指南:第二章

    URL概览 前面提到,URL资源是HTTP协议所使用的寻找资源位置的定位符.分为三个部分,主要的结构是: 方案://服务器/路径 这种结构使得网络上的每一个资源都只有唯一的命名方法,从而使得浏览器可以 ...

  5. Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)

    前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...

  6. 《SDN核心技术剖析和实战指南》第一章小结

    第一章主要是概况.新技术有一个特点是,每家都有不同的说法.这里我只说说我比较认同的部分. SDN的核心概念大概有两个:转发面与控制面分离.开发可编程化.书里还说逻辑上集中控制,其实这个就可以从转发与控 ...

  7. PMP备考指南之第二章:项目运作环境

    本文已同步至 GitHub/Gitee/公众号,感兴趣的同学帮忙点波关注~ 第二章:项目运作环境 1. 事业环境因素.组织过程资产 事业环境因素 Enterprise Environmental Fa ...

  8. Windows Forms编程实战学习:第二章 欢迎使用Visual Studio

    第二章 欢迎使用Visual Studio 1,AssemblyInfo文件 包含程序集的属性,向应用程序添加元数据 [assembly:<attribute>(<setting&g ...

  9. java并发编程实战笔记---(第二章)线程安全:正确性

    ThreadA__________     同步 ______________ 异步 ___________     异步 ThreadB__________         ____________ ...

随机推荐

  1. maven profile实现多环境配置

    每次项目部署上线都需要手动去修改配置文件(比如数据库配置,或者一个自定义的配置)然后才能打包,很麻烦,网上找到 maven profile可以完成这个工作,记录如下: 环境:eclipse + spr ...

  2. pyCharm中BeautifulSoup应用

    BeautifulSoup 是第三方库的工具,它包含在一个名为bs4的文件包中,需要额外安装,安装方式 非常简单,进入python的安装目录,再进入scripts子目录,找到pip程序, pip in ...

  3. transfer model derived to fk model format

    It should be noted that when using fk, the definition of model format is as belows: 1: 2: when using ...

  4. Mac上配置maven+eclipse+spark开发环境

    1.安装jdk 2.下载scala-ide.官网:http://scala-ide.org 3.安装maven 4.在eclipse中,配置maven的安装了路径.偏好设置--->maven-- ...

  5. 2016/12/22 dplの课练

    1.sort -nk 1 -t - 3 2.sort -nk 1 -t - 2 3.sort -nk 2 -t - 1 3./etc/passwd根据用户id的大小排序,从小到大的排序输出 sort ...

  6. ueditor的用法

    今天做了一下百度富文本编辑器,遇到了一些问题,现在来总结一下: (1)jQuery没有引用,解决方法:引用jQuery并且放在所有的js前面 (2)没有报错,但是样式显示不出来.解决方法:css引用的 ...

  7. NodeJs 设置跨域后页面全部变成了源码在浏览器上显示

    百度搜索跨域后得到 app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin" ...

  8. JDK8.0接口中的默认方法和静态方法

    我们在接口中通常定义的方法是抽象方法,即没有方法体,只有返回值类型和方法名:(public abstract) void Method(); 类在实现接口的时候必须重写抽象方法才可以 jdk8中新加的 ...

  9. CnPack组件包的安装与使用

    如果你用过Eclipse.NotePad++等等工具,再试试用刚装好Delphi写代码会很痛苦,你是否觉得Delphi的代码编辑器很不友好? 那就去了解一下CnPack吧,给你的Delphi装上它绝对 ...

  10. 【Spring】文件上传

    一:引入所需jar包 // https://mvnrepository.com/artifact/commons-fileupload/commons-fileuploadcompile group: ...