一、计算图中的操作

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

声明张量和占位符。这里,创建一个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. 本地存储localStorage sessionStorage 以及 session 和cookie的对比和使用

    cookie和session都是用来跟踪浏览器用户身份的会话方式. 1.验证当前服务中继续请求数据时,哪些缓存数据会随着发往服务器? 只有cookie中设置的缓存数据会发送到服务器端 2. 强调几点: ...

  2. Asp .Net Core Spa (一) - 入门

    第一次写文章, 很久之前就想写来着了, 文章哪里不清楚的, 也请多多提出意见. 最近发现用 .net core + spa (single page application) 这个组合的人也变多了, ...

  3. Python 字典dict相关知识

    字典是无序的,多次print输出的结果不一样. 字典的key可以是数字.字符串.元组.布尔值(True为1,False为0,不可以和其他key值重复):列表和字典不能作为key. 字典的value可以 ...

  4. spyder常用功能

    最近和同学讨论到spyder的使用技巧,所以就结合之前在网上看到网友的总结( https://blog.csdn.net/peiwang245/article/details/78528098)和自己 ...

  5. java集合(一)

  6. 学号 20175223 《Java程序设计》第 6 周学习总结

    目录 教材学习内容总结 代码调试中的问题和解决过程 1. 编译运行时,跳过 Scanner.nextLine() 语句. 2. 提示 NullPointerException 错误. [代码托管] 学 ...

  7. re正则表达式匹配字符串中的数字

    re.match(r'.*-(\d*).html',url_1).group(1) \d+匹配1次或者多次数字,注意这里不要写成*,因为即便是小数,小数点之前也得有一个数字:\.?这个是匹配小数点的, ...

  8. div嵌套,常见左右分类栏目

    最终效果图如下: html代码如下: <div class="smalItem"> <div class="leftnav"> < ...

  9. JS的call与apply的用法

    call与apply的第一个参数都是需要调用的函数对象,在函数体内这个参数就是this的值,剩余的参数是需要传递给函数的值,call与apply的不同就是call传的值可以是任意的,而apply传的剩 ...

  10. Sql Server 默认值

    --1.取得数据库所有表的默认值: select t3.name as 表名,t1.name as 字段名,t2.text as 默认值 ,t4.name from syscolumns t1,sys ...