线性回归问题TensorFlow实战

使用Tensorflow进行算法设计与训练的核心步骤

  1. 准备数据
  2. 构建模型
  3. 训练模型.
  4. 进行预测

上述步骤是我们使用Tensorflow进行算法设计与训练的核心步骤,贯穿于后面介绍的具体实战中。本章用一一个简单的例子来讲解这几个步骤。

线性方程二元线性回归的图像 二元线性回归数据例题_数据

本例通过生成人工数据集。随机生成一个近似采样随机分布,使得二元线性回归的图像 二元线性回归数据例题_二元线性回归的图像_02二元线性回归的图像 二元线性回归数据例题_python_03, 并加入- -个噪声,噪声的最大振幅为0.4

生成人工数据

#在Jupyter中,使用matplotIib显示图像需要设置为 inline 模式,
#否则不会现实图像
%matplotlib inline

import matplotlib. pyplot as plt
import numpy as np #载入numpy
import tensorflow as tf #载入Tensorflow

#设置随机数种子
np.random.seed (5)  #产生相同的随机数

首先,生成输入数据。我们需要构造满足这个函数的x和y同时加入- -些不满足方程的噪声.

#直接采用np生成等差数列的方法,生成100个点, 每个点的取值在-1 ~1之间
x_data = np. linspace(-1, 1,100) 
#y=2x+1+噪声,其中,噪声的维度与x _data一致
y_data=2*x_data +1.0 + np. random.randn(*x_data.shape) * 0.4
# np.random.randn(10)
# 返回10个根据标准正太分布获得的数据得到的一维数组
# #实参的前面加上*和**时,就意味着拆包。
#单个*表示将元组拆成- - 个个单独的实参
#本例中,np. random. randn (*x data. shape)和np. random. randn (100)功能相同

利用matplotlib画出生成结果

#画出随机生成数据的散点图
plt.scatter(x_data, y_data)
#画出我们想要学习到的线性函数y=2x +1

构建模型

定义训练数据的占位符,x是特征值,y是标签值。

x = tf. placeholder("float",name ="x")
y = tf. placeholder("float",name ="y")

定义模型函数

def model(x,w,b):
    return tf.multiply(x,w)+b

创建变量
Tensorflow变量的声明函数是tf. Variable;tf.Variable的作用是保存和更新参数;●变量的初始值可以是随机数、常数,或是通过其他变量的初始值计算得到。

#构建线性函数的斜率,变量w
w = tf. Variable(1.0, name="w0")  #1.0初始值无所谓
#构建线性函数的截距,变量b
b = tf. Variable(0.0,name="b0"  )
# pred是预测值,前向计算
pred = model(x, w,b)

训练模型

# 设置训练参数
#迭代次数(训练轮数)
train_epochs = 10
#学习率
learning_rate = 0.05   #设置0.01到0.1之间,根据以往的经验,设置为0.05

定义损失函数

损失函数用于描述预测值与真实值之间的误差,从而指导模型收敛方向;常见损失函数:均方差(Mean Square Error, MSE) 和交叉熵(cross- entropy)

L2损失函数

#采用均方差作为损失函数
loss_function = tf. reduce_mean(tf.square(y-pred))

定义优化器

定义优化器Optimizer,初始化一个GradientDescentOptimizer;设置学习率和优化目标:最小化损失。

#梯度下降优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)

创建会话

#声明会话
sess = tf. Session()
#变量初始化
init = tf.global_variables_initializer()
sess.run(init)

迭代训练

模型训练阶段,设置迭代轮次,每次通过将样本逐个输入模型,进行梯度下降优化操作每轮迭代后,绘制出模型曲线

#开始训练,轮数为epoch,采用SGD随机梯度下降优化方法
for epoch in range (train_epochs) :
    for xs,ys in zip(x_data, y_data) :
        _,loss=sess.run([optimizer, loss_function], feed_dict={x: xs, y: ys})
    b0temp=b.eval(session=sess) 
    wOtemp=w.eval(session=sess)
    plt.plot (x_data, wOtemp * x_data + b0temp )# 画图
print("w: ",sess.run(w)) #w的值应在2的附近
print("b: ",sess.run(b)) #b的值应该在1的附近
#可视化
plt.scatter(x_data,y_data,label='Original data')
plt.plot(x_data,x_data * sess.run(w)+sess.run(b),\
        label="Fitted line",color='r',linewidth=3)
plt.legend(loc=2)

进行预测

x_test=3.21

predict=sess.run(pred,feed_dict={x:x_test})
print("预测值: %f" % predict)

target=2*x_test+1.0
print("目标值: %f" % target)

以上是利用Tensorflow训练-个线性模型并进行预测的完整过程。通过逐渐降低损失值loss来训练参数w和b拟合y = 2x + 1中的系数2和1。

小结

(1)生成人工数据集及其可视化

(2)构建线性模型

(3)定义损失函数

(4)定义优化器、最小化损失函数

(5)训练结果的可视化

(6)利用学习到的模型进行预测.

显示损失值

#对kernel进行restart释放内存空间,对变量情况

#开始训练,轮数为epoch, 采用SGD随机梯度下降优化方法
display_step=10 #控制显示loss的粒度
step = 0 #记录训练步数
loss_list = [ ] #用于保存loss值的列表

for epoch in range(train_epochs):
    for xs,ys in zip(x_data,y_data):
        _,loss=sess.run([optimizer,loss_function],feed_dict={x:xs,y:ys})
        ##显示损失值loss
        # display_ step:控制报告的粒度
        #例如,如果display step 设为2,则将每训练2个样本输出- -次损失值
        #与超参数不同,修改display_ step 不会更改模型所学习的规律
        loss_list. append(loss)
        step=step+1
        if step % display_step==0:
            print("Train Epoch:",'%02d' % (epoch+1),"Step :%03d" % (step),\
                 "loss=",   '{:.9f}'.format(loss))
        b0temp=b.eval(session=sess)
        w0temp=w.eval(session=sess)
        plt.plot(x_data,w0temp* x_data+b0temp )#画图
plt.plot(loss_list)
plt.plot(loss_list,'r+')

多元线性回归问题TensorFlow实践(波士顿房价预测)

波士顿房价数据

波士顿房价数据集包括506个样本,每个样本包括12个特征变量和该地区的平均房价。房价(单价)显然和多个特征变量相关,不是单变量线性回归(- 元线性回归)问题。选择多个特征变量来建立线性方程,这就是多变量线性回归(多 元线性回归)问题

下载泰坦尼克号上旅客的数据集

#下载泰坦尼克号上旅客的数据集
import urllib.request
import os
data_url="http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic3.xls"

data_file_path="titanic3.xls"   #当前路径下的位置

if not os.path.isfile(data_file_path):
    result=urllib.request.urlretrieve(data_url,data_file_path)
    print('download:',result)
    
else:
    print(data_file_path,'data file already esists.')

字段

字段说明

数据说明

pclass

舱等

1头等;2二等;3三等

survival

是否生存

0否;1是

name

姓名

sex

性别

Female女性;male男

age

年龄

sibsp

兄弟姐妹或者配偶在船上的数量

parch

双亲或者子女也在船上的数量

ticked

船票号码

fare

船票费用

cabin

舱位号码

embarked

登船港口

C=Cherbourg;A=queenstown;S=southampton

使用Pandas进行数据处理

import numpy 
import pandas as pd
#读取数据文件,结果为DataFrame格式
df_data = pd.read_excel(data_file_path)
##查看数据摘要
df_data.describe()

survival (是否生存)是标签字段,其他是候选特征字段

筛选提取需要的特征字段,去掉ticket, cabin等

#筛选提取需要的特征字段,去掉ticket, cabin等
selected_cols=['survived','name','pclass','sex','age','sibsp','fare','embarked']
selected_df_data=df_data[selected_cols]

survived是标签,name为区别暂时保留,其他的为特征

数据准备(相关操作)

波士顿房价

#获取df的值,返回二维列表
df=df.values

#把df转换成np的数组格式
df=np.array(df)

#x_data为前12列特征数据
x_data=df[:,:12]

#y_data为最后一列数据
y_data=df[:,12]

#df.shape 树蕨维数性质
from sklearn.datasets import load_boston
boston = load_boston()
df=boston.data
#数据集未曾归一化,结果可能导致异常
x_data=boston.data[:,:12]
#pd.DataFrame(x_data)
y_data=boston.target
#特征数据归一化
#对特征数据[0到11]列做(0-1)归一化
for i in range(12) :
    df[:, i]=df[:, i]/(df[:, i].max()-df[:,i].min())
# x data为归一化后的前12列特征数据
x_data = df[:, :12]
# y_ data 为最后1列标签数据
y_data = df[:,12]

模型定义

定义训练数据占位符

#定义特征数据和标签数据的占位符
x = tf. placeholder(tf.float32,[None,12],name ="X") # 12个特征数据(12列)
x = tf. placeholder(tf.float32,[None,1],name ="Y") # 1个特征数据(1列)

#[None,12]数据结构:行不管,列一个

定义模型结构

#定义模型函数
##定义了一个命名空间
with tf.name_scope("Model"):  #把内部相关的节点打包在一起
    # w初始化值为shape=(12, 1)的标准差为0.01的随机数填充
    w = tf. Variable(tf.random_normal([12,1],stddev=0.01),name="w")
    
    # b初始化值为1.0
    b = tf. Variable(1.0, name="b")
    # w和x是矩阵相乘,用matmul,不能用mutiply或者*
    #y=x1w1+x2w2+...+xnwn+b
    def model(x, w,b):
        return tf.matmul(x,w)+b
    #init = tf.global_variables_initializer()
    #预测计算操作,前向计算节点
    pred=model(x,w,b)

模型训练

损失函数

#定义均方误差损失函数
with tf.name_scope("LossFunction"):
    loss_function=tf.reduce_mean(tf.pow(y-pred,2))
#设置训练超参数
train_epochs=50
learning_rate=0.01

优化器

#创建优化器
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)

常用优化器

tf.train.GradientDescentOptimizer梯度下降算法优化器

tf.train.GradientDescentOptimizer( learning_rate, use_locking=False, name='GradientDescent', )

tf.train.AdadeltaOptimizerAdaDelta,是google提出的一种对于AdaOptimizer的改进,同样是一种自适应的优化器,在看上面ada优化器的时候我们会发现,当训练时间越来越长的时候,分母会越来越大因此导致所有的该变量都趋向于变为0,这样就会导致训练停止,可能导致没有充分的训练。为了解决这个问题,google提出了adadelta算法,加入了一个ρ参数,使得分母不仅仅在不断地积累,同时也乘参数使其不断的减小。

tf.train.AdadeltaOptimizer( learning_rate=0.001, rho=0.95, epsilon=1e-08, use_locking=False, name='Adadelta', )

tf.train.AdagradOptimizer自适应的梯度下降算法。其主要的思想是,如果一个可学习的参数已经梯度下降了很多,则减缓其下降的速度,反之如果一个参数和初始化相比没有下降很多,保证它有一个比较大的下降速度。和之前的对所有参数“一视同仁”的方法相比,该方法更加的“因材施教”。

tf.train.AdagradOptimizer( learning_rate, initial_accumulator_value=0.1, use_locking=False, name='Adagrad', )

tf.train.MomentumOptimizer这个函数是带动量的梯度下降,与之前的区别就是在一次梯度下降的计算时,同时考虑到上一次梯度下降的大小和方向,就好像梯度下降是有惯性一样

tf.train.MomentumOptimizer( learning_rate, momentum, use_locking=False, name='Momentum', use_nesterov=False, )

tf.train.AdamOptimizer全称是Adagrad双重平均算法(Dual Averaging algorithm)

tf.train.AdamOptimizer( learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False, name='Adam', )

tf.train.FtrlOptimizer

tf.train.ProximalGradientDescentOptimizer接近梯度下降方法,这个是tf取的名字,其实在文章中,作者简称该梯度下降算法为folos,之所以叫接近的梯度下降算法,是因为作者在原梯度下降算法的基础上加入了修正,进而解决了一些不可微的问题

tf.train.ProximalGradientDescentOptimizer( learning_rate, l1_regularization_strength=0.0, l2_regularization_strength=0.0, use_locking=False, name='ProximalGradientDescent', )

tf.train.ProximalAdagradOptimizer

tf.train.RMSPropOptimizer

声明会话

sess=tf.Session()
init=tf.global_variables_initializer()
sess.run(init)

迭代训练ke

for epoch in range(train_epochs):
    loss_sum=0.0
    for xs,ys in zip(x_data,y_data):
        xs=xs.reshape(1,12)
        ys=ys.reshape(1, 1)
        #feed数据必须和placeholder的shape一致
        _,loss=sess.run([optimizer,loss_function],feed_dict={x:xs,y:ys})
        loss_sum=loss_sum+loss
        #打乱数据顺序
        xvalues=random.shuffle(x_data)
        yvalues=random.shuffle(y_data)
        
        b0temp=b.eval(session=sess)
        w0temp=w.eval(session=sess)
        loss_average=loss_sum/len(y_data)
        
        print('epoch',epoch+1,"loss=",loss_average,"b=",b0temp,"w=",w0temp)

可能会出现结果异常的原因:要考虑不同特征值取值范围大小的影响。

因为用归一化:二元线性回归的图像 二元线性回归数据例题_tensorflow_04

特征数据归一化

#对特征数据[0到11]列做(0-1)归一化
for i in range(12) :
    df[:, i]=df[:, i]/(df[:, i].max()-df[:,i].min())
# x data为归一化后的前12列特征数据
x_data = df[:, :12]
# y_ data 为最后1列标签数据
y_data = df[:,12]

模型应用

模型一般应该用来预测新的样本的值。本例506条数据都用来训练了,暂时没有新的数据

n=348  #指定一条来看效果
#n=np.random.randint(506) #随机确定一条来看
print(n)
x_test=x_data[n]

x_test=x_test.reshape(1,12)
predict=sess.run(pred,feed_dict={x:x_test})
print("预测值: %f" %predict)

target=y_data[n]
print("标签值: %f" % target)

思考:该不该把全部的数据都参与训练?

可视化训练过程中的损失值