本文整理自知乎专栏深度炼丹,转载请征求原作者同意。

本文的全部代码都在原作者GitHub仓库github

CS20SI是Stanford大学开设的基于Tensorflow的深度学习研究课程。

TensorFlow中的Linear Regression

我们用tensorflow实现一个线性回归的例子。

问题:希望找到城市中纵火案和盗窃案之间的关系,纵火案的数量是\(X\),盗窃案的数量是\(Y\),我们假设存在如下线性关系:\(Y=wX+b\)。

TensorFlow实现

  1. 首先定义输入\(X\)和目标\(Y\)的占位符(placeholder)
    X = tf.placeholder(tf.float32, shape=[], name='input')
    Y = tf.placeholder(tf.float32, shape=[], name='label')

里面shape=[]表示标量(scalar)

  1. 定义需要更新和学习的参数\(w\)和\(b\)

    w = tf.get_variable('weight', shape=[], initializer=tf.truncated_normal_initializer())
    b = tf.get_variable('bias', shape=[], initializer=tf.zeros_initializer())
  2. 定义模型的输出和误差函数,这里使用均方误差\((Y-Y\_predicted)^2\)

    Y_predicted = w * X + b
    loss = tf.squre(Y - Y_predicted, name='loss')
  3. 定义优化函数,这里使用简单梯度下降,这里的学习率可以是常量和tensor

    optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimizer(loss)

tensorflow如何判断哪些参数更新,哪些不更新呢?tf.Variable(trainable=False)表示不对该参数更新,默认为True

  1. session中做运算
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
    writer = tf.summary.FileWriter('./linear_log', graph=sess.graph)
    sess.run(init)
    for i in range(100):
    total_loss=0
    for x, y in data:
    _, l = sess.run([optimizer, loss], feed_dict={X:x, Y:y})
    total_loss+=1
    print('Epoch {0}: {1}'.format(i, total_loss/n_samples))

上述步骤源代码:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import xlrd DATA_FILE = 'data/fire_theft.xls' # step 1:加载数据
book = xlrd.open_workbook(DATA_FILE, encoding_override='utf-8')
sheet = book.sheet_by_index(0)
data = np.asarray([sheet.row_values(i) for i in range(1, sheet.nrows)], dtype=np.float32)
n_samples = sheet.nrows - 1 # step 2:定义输入输出的占位符
X = tf.placeholder(tf.float32, shape=[], name='input')
Y = tf.placeholder(tf.float32, shape=[], name='label') # step 3:定义需要更新的参数w和b
w = tf.get_variable('weight',shape=[],initializer=tf.truncated_normal_initializer)
b = tf.get_variable('bias', shape=[], initializer=tf.zeros_initializer) # step 4:定义模型输出和误差函数,这里使用均方误差
Y_predict = w * X + b;
loss = tf.square(Y - Y_predict, name='loss') # step 5:定义优化函数,这里使用简单梯度下降
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimize(loss) # step 6:在session中运算
init = tf.global_variables_initializer()
with tf.Session() as sess:
writer = tf.summary.FileWriter('./linear_log', graph=sess.graph)
sess.run(init)
for i in range(100):
total_loss = 0
for x, y in data:
_, l = sess.run([optimizer, loss], feed_dict={X: x, Y:y})
total_loss += l
print('Epoch {0}: {1}'.format(i, total_loss/n_samples))
w, b = sess.run([w, b])
writer.close() # step 7:画出结果
X, Y = data.T[0], data.T[1]
plt.plot(X,Y, 'bo', label='Real data')
plt.plot(X,X*w+b, 'r', label='Predicted data')
plt.legend()
plt.show()

可视化

打开tensorboard查看我们的结构图



最后将数据点和预测直线画出来:

如何改善模型

  1. 增加维度,原始模型是\(Y=wX+b\),我们可以提升一维,使其变成\(Y=w_1X^2+w_2X+b\)
  2. 换一种计算loss的方法,比如huber loss,当误差小的时候用均方误差,误差大的时候使用绝对值误差

\[L_\delta(y,f(x))=\left\{\begin{array}{ll}\frac{1}{2}(y-f(x))^2&\textrm{for}|y-f(x)|\leq\delta \\ \delta|y-f(x)|-\frac{1}{2}\delta^2&\textrm{otherwise}\end{array} \right.
\]

在实现huber loss的时候,因为tf是以图的形式来定义,所以不能使用逻辑语句,比如if等,我们可以使用TensorFlow中的条件判断语句,比如tf.wheretf.case等等,huber loss的实现方法如下:

python def huber_loss(labels, predictions, delta=1.0): residual = tf.abs(prediction - labels) condition = tf.less(residual, delta) small_res = 0.5 * residual**2; large_res = delta * residual - 0.5 * delta**2 return tf.where(condition, small_res, large_res)

关于Optimizer

TensorFlow会自动求导,然后更新参数,使用一行代码:

tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimize(loss)

这里的过程我们分开来细讲。

自动梯度

  1. 首先是我们定义好优化函数:
    opt = tf.train.GradientDescentOptimizer(learning_rate)
  2. 定义好优化函数后,可以通过如下步骤计算梯度:
    grads_and_vars=opt.compute_gradients(loss, <list of variables>)

第二个参数是一个list,该函数会计算loss对于变量列表里的每一个变量的梯度。得到的grads_and_vars是一个list of tuple,list中的每个tuple都是由(gradient, variable)对构成,我们可以通过使用如下代码提取出来:

python get_grads_and_vars=[(gv[0],gv[1]) for gv in grads_and_vars]

  1. 更新参数
    opt.apply_gradients(get_grads_and_vars)

举个例子:

import tensorflow as tf

x = tf.Variable(5, dtype=tf.float32)
y = tf.Variable(3, dtype=tf.float32) z = x**2 + x * y + 3 sess = tf.Session()
# 初始化变量
sess.run(tf.global_variables_initializer()) # 定义优化函数
optimizer= tf.train.GradientDescentOptimizer(learning_rate=0.1) # 计算z关于x,y的梯度
grads_and_vars = optimizer.compute_gradients(z, [x, y]) # 获取变量
get_grads_and_vars = [(gv[0], gv[1]) for gv in grads_and_vars] # dz/dx = 2*x + y = 13
# dz/dy = x = 5
print('grads and variables')
print('x: grad {}, value {}'.format(sess.run(get_grads_and_vars[0][0]), sess.run(get_grads_and_vars[0][1]))) print('y: grad {}, value {}'.format(sess.run(get_grads_and_vars[1][0]), sess.run(get_grads_and_vars[1][1]))) print('Before optimization')
print('x: {}, y:{}'.format(sess.run(x), sess.run(y))) # 优化参数
opt=optimizer.apply_gradients(get_grads_and_vars)
# x = x-0.1*dz/dx = 5-0.1*13=3.7
# y = y-0.1*dz/dy = 3-0.1*5 = 2.5
print('After optimization using learning rate 0.1')
sess.run(opt)
print('x: {:.3f}, y: {:.3f}'.format(sess.run(x), sess.run(y)))
sess.close()

可得到结果:



在实际操作中,不需要手动更新参数,optimizer类可以帮我们自动更新。另外还有一个函数也能够计算梯度。

tf.gradients(ys, xs, grad_ys=None, name='gradients', colocate_gradients_with_ops=False,gate_gradients=False, aggregation_method=None)

该函数返回一个list,list的长度就是xs的长度,list中每个元素都是\(sum_{ys}(d(ys)/dx)\)。

实际运用: 这个方法对于只训练部分网络非常有用,我们能够使用上面的函数只对网络中一部分参数求梯度,然后对他们进行梯度的更新。

优化函数类型

SGD只是TF的一个小的更新方法,目前支持的更新方法如下:

tf.train.GradientDescentOptimizer
tf.train.AdadeltaOptimizer
tf.train.AdagradOptimizer
tf.train.AdagradDAOptimizer
tf.train.MomentumOptimizer
tf.train.AdamOptimizer
tf.train.FtrlOptimizer
tf.train.ProximalGradientDescentOptimizer
tf.train.ProximalAdagradOptimizer
tf.train.RMSPropOptimizer

TensorFlow中的Logistic Regression

我们使用简单的logistic regression来解决分类问题,使用MNIST手写字体,模型公式如下:

\[\begin{array}{rl}logits &= X*w+b \\Y_{predicted} &={\bf softmax}(logits)\\
loss &= {\bf CrossEntropy}(Y, Y_{predicted})\end{array}\]

TensorFlow实现

  1. 读取MNIST数据集
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('./data/mnist', one_hot = True)
  1. 定义占位符和权重参数

    x = tf.placeholder(tf.float32, shape=[None, 784], name='image')
    y = tf.placeholder(tf.int32, shape=[None, 10], name='label') w = tf.get_variable('weight', shape=[784,10], initializer=tf.truncated_normal_initializer())
    b = tf.get_variable('bias', shape=[10], initializer=tf.zeros_initializer())

    输入数据的shape=[None, 784]表示第一维接受任何长度的输入,第二维等于784因为\(28\times 28=784\)。权重w使用均值为0,方差为1的正太分布,偏置b初始化为0.

  2. 定义预测结果、loss和优化函数

    logits = tf.matmul(x, w)+b
    entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(entropy, axis=0)
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

    使用tf.matmul做矩阵乘法,然后使用分类问题的loss函数交叉熵,最后将一个batch中的loss求均值,对其使用随机梯度下降法。

  3. 数据集中有测试集,可以在测试集上验证准确率

    preds = tf.nn.softmax(logits)
    correct_preds = tf.equal(tf.argmax(preds, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32), axis=0)

    首先对输出结果进行softmax得到概率分布,然后使用tf.argmax得到预测的label,使用tf.equal得到label和实际的label相同的个数,这是一个长为batch的0-1向量,然后使用tf.reduce_sum得到正确的总数。

  4. 在session中运算

逻辑回归部分代码如下:

import tensorflow as tf
import time
# 模型参数
learning_rate = 0.01
batch_size = 128
n_epochs = 10 # step 1:读取数据集
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('./data/mnist', one_hot = True) # step 2:定义占位符和更新变量
x = tf.placeholder(tf.float32, shape=[None, 784], name='image')
y = tf.placeholder(tf.int32, shape=[None, 10], name='label') w = tf.get_variable('weight', shape=[784,10],initializer=tf.truncated_normal_initializer)
b = tf.get_variable('bias', shape=[10], initializer=tf.zeros_initializer) # step 3:定义结果、loss和优化函数
logits = tf.matmul(x, w) + b
entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss = tf.reduce_mean(entropy,axis=0)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) preds = tf.nn.softmax(logits)
correct_preds = tf.equal(tf.argmax(preds, 1), tf.argmax(y, 1))
accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32), axis=0) with tf.Session() as sess:
writer = tf.summary.FileWriter('./logistic_log', graph=sess.graph)
start_time = time.time()
sess.run(tf.global_variables_initializer())
n_batches = int(mnist.train.num_examples / batch_size)
for i in range(n_epochs):
total_loss=0
for _ in range(n_batches):
X_batch, Y_batch = mnist.train.next_batch(batch_size)
_, loss_batch = sess.run([optimizer, loss], feed_dict={x: X_batch, y:Y_batch})
total_loss+=loss_batch
print('Average loss epoch {0}:{1}'.format(i, total_loss/n_batches)) print('Total time: {0} seconds'.format(time.time()-start_time))
print('Optimization Finished!') # test model
n_batches = int(mnist.test.num_examples / batch_size)
total_correct_preds = 0 for i in range(n_batches):
X_batch, Y_batch = mnist.test.next_batch(batch_size)
accuracy_batch = sess.run(accuracy, feed_dict={x:X_batch,y:Y_batch})
total_correct_preds += accuracy_batch
print('Average {0}'.format(total_correct_preds/mnist.test.num_examples))

结果可视化

最后可以得到训练集的loss的验证集准确率如下



可以发现经过10 epochs,验证集能够实现74%的准确率。同时,我们还能够得到tensorboard可视化如下。

CS20SI-tensorflow for research笔记: Lecture3的更多相关文章

  1. Google TensorFlow深度学习笔记

    Google Deep Learning Notes Google 深度学习笔记 由于谷歌机器学习教程更新太慢,所以一边学习Deep Learning教程,经常总结是个好习惯,笔记目录奉上. Gith ...

  2. TensorFlow.org教程笔记(二) DataSets 快速入门

    本文翻译自www.tensorflow.org的英文教程. tf.data 模块包含一组类,可以让你轻松加载数据,操作数据并将其输入到模型中.本文通过两个简单的例子来介绍这个API 从内存中的nump ...

  3. CS20SI-tensorflow for research笔记: Lecture2

    本文整理自知乎专栏深度炼丹,转载请征求原作者同意. 本文的全部代码都在原作者GitHub仓库github CS20SI是Stanford大学开设的基于Tensorflow的深度学习研究课程. Tens ...

  4. CS20SI-tensorflow for research笔记: Lecture1

    本文整理自知乎专栏深度炼丹,转载请征求原作者同意. 本文的全部代码都在原作者GitHub仓库github CS20SI是Stanford大学开设的基于Tensorflow的深度学习研究课程. 什么是T ...

  5. 『TensorFlow』读书笔记_Inception_V3_下

    极为庞大的网络结构,不过下一节的ResNet也不小 线性的组成,结构大体如下: 常规卷积部分->Inception模块组1->Inception模块组2->Inception模块组3 ...

  6. TensorFlow深度学习笔记 Tensorboard入门

    转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程: https://ww ...

  7. TensorFlow深度学习笔记 循环神经网络实践

    转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程地址 视频/字幕下载 加 ...

  8. TensorFlow 深度学习笔记 卷积神经网络

    Convolutional Networks 转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Is ...

  9. TensorFlow 深度学习笔记 TensorFlow实现与优化深度神经网络

    转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程地址 视频/字幕下载 全 ...

随机推荐

  1. django ajax 及批量插入数据 分页器

    ``` Ajax 前端朝后端发送请求都有哪些方式 a标签href GET请求 浏览器输入url GET请求 form表单 GET/POST请求 Ajax GET/POST请求 前端朝后端发送数据的编码 ...

  2. netstat、ps、top 、kill 命令备忘

    1.ps命令用于显示当前进程 (process) 的状态. -aux 显示所有包含其他使用者的行程. -e 显示所有进程. -f 全格式输出. 一般带参数 -ef 或者 -aux ,差别不大. 区别: ...

  3. tomcat 网页管理tomcat

    一.设置管理员账户密码 进入tomcat安装目录 ->进入conf目录->修改user.xml->加入下面内容 模板 <role rolename="manager- ...

  4. kafka Network

    Kafka network Processor SocketServer.Processor override def run() { startupComplete() try { while (i ...

  5. vertx的HttpServer模块

    Start HttpServer /** * 启动 HttpServer * multi instances 采用 synchronized防止线程安全问题 * addHandlers 方法是acto ...

  6. memcpy一种实现方法

    #include<stdio.h> #include<stdlib.h> void* memncpy(void* dest, const void* src, int coun ...

  7. ansible的modules

    fetch   :从远端服务器拉取文件到本地 dest 依赖   本地存放拉取到的文件路径, 如果flat=yes,则会在该路径下直接存放文件, 如果flat=no,则会在该路径下生成每个服务器的in ...

  8. Angular changeDetction

    ChangeDection 检测程序内部状态,然后反映到UI上. 引起状态变化:Events,XHR,Timers ApplicationRef监听NgZone的onTurnDone,然后执行检测. ...

  9. 关于jQuery的append方法不能多次添加同一个DOM元素的解决方法

    资料来自:https://segmentfault.com/q/1010000007677851?_ea=1419689 append()方法在jQuery中是使用appendChild()实现的,实 ...

  10. SFTP服务的使用!!

    在Client端安装Xshell或者SecureCRT等具有SFTP文件传输功能的软件,在服务器端安装好SFTP服务并启动,就可以用SFTP传输文件了! from:   http://www.cnbl ...