Linear Regression with TensorFlow

原文传送门: http://t.hengwei.me/post/linear-regression-with-tensorflow.html

TensorFlow除了可以用于一些基本的深度学习算法(*NN)之类,当然也可以用于最简单的线性回归。毕竟以后我们所有接触到的如Logistics Regression, Neural Network 等都是以最基本的线性回归(Linear Regression)为基础的。本篇主要从简单的线性回归来展示运用TensorFlow工具做模型的一般过程。

前一节我们提到TensorFlow其最大的特点便是把Tensor图结构的定义和执行分开。任何时候变量和函数的定义与执行总是分开的。这种类Lisp语言风格的方式扩展性特别好,可以自由组合各种Tensor节点,特别适合新模型和算法的探索。具体来说,针对Machine Learning算法而言,一个更为细化的Tensor定义和执行的过程主要包括:数据读取数据可视化于模型选择placeholder定义Variable定义构建模型定义损失函数定义Optimizer变量初始化训练模型输出模型参数,预测

等。 下面我们继续以Stanford的CS20Si课程的数据集为基础,来展示利用TensorFlow做线性回归的整个过程,并对整个步骤极可能详细的描述,以便为后来的LR,CNN等过程铺路。

1.数据集获取与预处理

数据集使用Cengage Learning提供的芝加哥大都会区住宅盗窃与火灾的统计数据,数据集描述如下:

In the following data pairs
X = fires per 1000 housing units
Y = thefts per 1000 population
within the same Zip code in the Chicago metro area
Reference: U.S. Commission on Civil Rights

我们下载excel版本的数据集到本地后,先读取数据到TensorFlow

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import xlrd

# local data file directory
DATA_FILE = "data/fire_theft.xls"

# STEP 0: read in data from xls file
book = xlrd.open_workbook(DATA_FILE, encoding_override="utf-8")
sheet = book.sheet_by_index(0)
lst = [sheet.row_values(i) for i in range(1, sheet.nrows)]
data = np.asarray(lst)
n_samples = sheet.nrows - 1

2.数据集抽样可视化与模型选择

模型和算法的选择在任何时候都是至关重要的过程,而对数据集有一个直观的印象更是重中之重<label for="sn-1" class="margin-toggle sidenote-number" style="box-sizing: border-box; margin: 0px 0px 5px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; vertical-align: baseline; display: inline; max-width: 100%; counter-increment: sidenote-counter 1;"></label>

Intuitive在模型特征的选择时尤为重要,有效的数据可视化往往使得接下来的工作事半功倍。本文中的数据集只是简单的二维数据集,可视化自然不成问题,对于高纬数据,往往需要一个降维的过程,如基本的PCA,或者是hinton大神的t-SNE,其在Mnist高纬数据集的可视化效果非常赞:

mnist tsne

同时推荐一个非常不错的Machine Learning领域的数据可视化博客Colah's Blog

。对该数据集我们可以画一个简单的二维数据分布图:

# STEP: 1: plot the data
X_axis, Y_axis = data.T[0], data.T[1]
plt.plot(X_axis, Y_axis, 'bo', label='Real data')
plt.ylim([0, 150])
plt.xlim([0, 45])
plt.legend()
plt.show()

分布如下所示:

fire theft

大致来看,数据集分布可以用一个简单的线性回归来适配,也可以整一个Quadratic函数来建模,当然此处为了演示线性回归,便先用线性回归来做。我们简单的选取模型为

Y = weight * X + bias

3.定义placeholder

既然模型确定了,我们便可以用TensorFlow的语言来定义模型图结构。placeholder是一种预先声明的function用来填充训练数据集的。对于线性回归而言,placeholder就是指X,Y,是来自测试数据集的,其不需要进行初始化,也不需要进行模型训练,只是在session run时feed真实的数据即可。

# STEP 2: create placeholder for input X(number of fire) and label Y(number of theft)
X = tf.placeholder(tf.float32, name="X")
Y = tf.placeholder(tf.float32, name="Y")

4. 定义Variable

相对于placeholder,Variable略为不同,前面一篇我们单独介绍过Variable的一些operation和属性。我们可以和placeholder来做个简单的对比,

Name placeholder Variable
type function Class
初始化 NO YES
模型训练更新 NO YES
存储 数据集群 参数服务器(PS)

Stack Overflow上有个关于两者区别的讨论值得一看

# STEP 3: create Variables(weight and bias here), initialize to 0.
w = tf.Variable(0.0, name="weight")
b = tf.Variable(0.0, name="bias")

5. 构建模型

这步很简单,依据第二部我们的模型选择,把其转换成Python表达,值得注意的是,由于是矩阵运算,如果X是高纬特征需要稍微考虑各个元素之间的位置。

# STEP 4: construct model to predict Y
Y_Predict = X * w + b

6. 定义损失函数

损失函数(loss function)的选择直接影响模型的训练复杂度和泛化效果。如针对linear regression最常见得损失函数式mean square error loss,即平方差损失。这种损失函数简单易用,但由于针对所有样本进行损失累计,一些outlier的点往往对整体模型有很大的影响,类似缺点的损失函数如absolute loss<label for="sn-1" class="margin-toggle sidenote-number" style="box-sizing: border-box; margin: 0px 0px 5px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; vertical-align: baseline; display: inline; max-width: 100%; counter-increment: sidenote-counter 1;"></label>

The squared loss function results in an arithmetic mean-unbiased estimator, and the absolute-value loss function results in a median-unbiased estimator (in the one-dimensional case, and a geometric median-unbiased estimator for the multi-dimensional case). The squared loss has the disadvantage that it has the tendency to be dominated by outliers—when summing over a set of samples, the sample mean is influenced too much by a few particularly large a-values when the distribution is heavy tailed: in terms of estimation theory, the asymptotic relative efficiency of the mean is poor for heavy-tailed distributions. -wikipedia

。还有一种叫做hubor loss的损失函数,相比于square error,其通过对偏离mean的点进行一定程度的loss惩罚(把损失近似成线性),使得 其对噪声样本(如离均值比较远的点)比较多的数据集有很好的效果。其和mean loss对比图一目了然:


huber mean loss
# STEP 5: define loss function(use square error here)
# hubor_loss = tf.losses.huber_loss(Y, Y_Predict) for Hubor loss.
loss = tf.square(Y - Y_Predict, name="loss")

7. 定义Optimizer

一个算法模型最终能否转化成实际可用的industry工程实践,很大程度上区别于在现有computer power下的优化算法优劣。机器学习的很多模型都是non-determinate的算法,损失函数也可能是non-convex的,比如可能存在local optimization的问题,这时候优化方法便至关重要。TensorFlow提供了一大坨Optimizers,比如:

  1. tf.train.Optimizer
  2. tf.train.GradientDescentOptimizer
  3. tf.train.AdadeltaOptimizer
  4. tf.train.AdagradOptimizer
  5. tf.train.AdagradDAOptimizer
  6. tf.train.MomentumOptimizer
  7. tf.train.AdamOptimizer
  8. tf.train.FtrlOptimizer
  9. tf.train.ProximalGradientDescentOptimizer
  10. tf.train.ProximalAdagradOptimizer
  11. tf.train.RMSPropOptimizer

每一个算法都值得讲好几章有么有,以后有时间会一一研究下,有篇总结的帖子可以参考下。简而言之,梯度下降有两个问题,1)可能会陷入局部最优。2)依赖于learning rate的设置

而这两点在针对一些特定数据集(如stock market的稀疏数据)的条件下可能会导致模型找不到(或者在一定的epoch内)找不到最优解。这里对于简单的mean square loss,一般选择梯度下降就够了。

# STEP 6: define optimizer(here we use Gradient Descent with learning rate of 0.001)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(loss)

8. 初始化与模型训练

到这里我们的基本模型定义已经完成,便需要设定一些基本的常量,或者对之前的Variable进行初始化。前一章节也大篇幅介绍了初始化的几种方法,再次不再赘述。初始化完毕便可以开始模型训练。模型定义完成后,模型的执行也基本是一行代码的事,唯一需要做的便是在Session里run时进行feed数据。

# define the epoch
epoch = 200
init = tf.initialize_all_variables()
# execute the model
with tf.Session() as sess:
    # STEP 7: initailize the necessary variable, in this case w and b.
    sess.run(init)

    # STEP 8: traning the model
    for i in range(epoch):
        for x, y in data:
            sess.run(optimizer, feed_dict={X: x, Y: y})

    # STEP 9: output the values of w and b.
    w_value, b_value = sess.run([w, b])

9. 效果评估与预测

训练出来的模型适配原始的数据集如下所示,第一幅图是采用square error的线,第二幅是采用hubor loss的线,可以看出对于outlier点有了很好的规避。

# plot the predict line.
plt.plot(Y_axis, Y_axis * w_value + b_value, 'r', label='Predicted data')
plt.ylim([0, 150])
plt.xlim([0, 45])
plt.legend()
plt.show()

square error
hubor error

参考

[2]

Tensorflow for Deep Learning Research.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容