零基础入门机器学习-tensorflow(四)

这次来做一个小项目,算是tensorflow入门级别的实践。手头有一份北京全年气温的数据,现在通过训练模型拟合出一条全年气温的曲线,可用于对北京某个日期下气温的预测。

数据获取与加工

从kaggle下载了北京PM2.5的全年数据,数据表中包含了全年气温,数据文件是CSV格式(下载地址:http://www.digeek.tech/download/PM25.csv),下面是数据文件的格式与内容:

表格中每一行表示北京一年中某一天凌晨0点的数据,一共365条数据,每天一条,本篇中只会用到温度数据。

下面是数据获取的代码部分:

# 引入tensorflow、numpy和matplotlib库

import tensorflow as tf

import numpy as np

import matplotlib.pyplot as plt

# 获取数据

data = np.genfromtxt('/Users/Bruce/Desktop/PM25.csv', dtype=float, delimiter=',', skip_header=1)

x_data = np.array([x[0] for x in data])[:, np.newaxis]

y_data = np.array([y[13] for y in data])[:, np.newaxis]

# 绘图,绘出训练数据

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.scatter(x_data, y_data)

plt.show()

print(x_data)

print("----------------------")

print(y_data)

为简单起见,x_data只获取序号,y_data则表示每天的数据,需要注意的是,获取数据后需要转格式成np.array,并且转换成 [n, 1] 矩阵。

通过matplotlib.pyplot库将数据绘制出来,如下图所示:

横坐标是日期,纵坐标是温度,在开始建模之前,还需要对数据做一些处理,因为x_data的范围是1-365,这个范围太大了,在机器学习过程中可能会遇到梯度爆炸,即无法拟合的情况,所以需要将x_data映射到0至1的范围内,这一过程称为归一化,公式是这样的:

下面将代码做了修改:

# 引入tensorflow、numpy和matplotlib库

import tensorflow as tf

import numpy as np

import matplotlib.pyplot as plt

# 获取数据

data = np.genfromtxt('/Users/Bruce/Desktop/PM25.csv', dtype=float, delimiter=',', skip_header=1)

x_ = np.array([x[0] for x in data])[:, np.newaxis]

# 数据归一化

amin, amax = x_.min(), x_.max()

# 求最大最小值

x_data = (x_ - amin)/(amax - amin)

y_data = np.array([y[13] for y in data])[:, np.newaxis]

# 绘图,绘出训练数据

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.scatter(x_data, y_data)

plt.show()

print(x_data)

print("----------------------")

print(y_data)

模型结构

模型分为输入层、隐藏层和输出层。

输入层就是现有的训练数据,日期与气温,这是 [n, 1] 的矩阵结构。输出层即通过机器学习或的预测值。在输入层和输出层之前还设计了1层隐藏层,隐藏层一共包含200个节点,大概的样子是这样的。

下面是代码实现:

#输入层

xs = tf.placeholder(tf.float32, [None, 1]) #占位符,None表示n*1维矩阵

ys = tf.placeholder(tf.float32, [None, 1]) #占位符,None表示n*1维矩阵

#隐层(200个神经元)

W1 = tf.Variable(tf.random_normal([1,200])) #权重,1*200的矩阵,并用符合正态分布的随机数填充

b1 = tf.Variable(tf.zeros([1,200]) + 0.1) #偏置,1*200的矩阵,使用0.1填充

Wx_plus_b1 = tf.matmul(xs,W1) + b1 #矩阵xs和W1相乘,然后加上偏置

output1 = tf.nn.sigmoid(Wx_plus_b1) #激活函数使用tf.nn.sigmoid

#输出层

W2 = tf.Variable(tf.random_normal([200,1])) #权重,200*1的矩阵,并用符合正态分布的随机数填充

b2 = tf.Variable(tf.zeros([1])+0.1) # 偏置,使用0.1填充

Wx_plus_b2 = tf.matmul(output1,W2) + b2

output2 = Wx_plus_b2 # 输出层不使用激活函数

输入层使用了placeholder;

输出层和隐藏层很类似,但是没有加激活函数,另外输出层的节点数量是1,实际会输出一个一维矩阵。

损失函数与训练算法

通过隐藏层和输出层的计算,会得到一个一维矩阵,矩阵中的元素是通过计算得出的每天对应的气温,这个计算值与训练样本中的气温值的差距就是损失,在计算损失时,使用了偏差平方求和,再取平均值的方式,如下:

#损失

loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys-output2),reduction_indices=[1])) #在第一维上,偏差平方后求和,再求平均值,来计算损失

机器学习的目的就是使损失降低,这里使用了梯度下降的方式来降低损失,关于梯度下降算法这里不做说明,基本逻辑是通过计算损失,去修改模型中的权重和偏置的值(反向传播),并计算新的损失,直至损失降低到可接受的范围内,这样就得到了模型的全部权重和偏置,即本篇中拟合曲线的实现公式。

train_step = tf.train.GradientDescentOptimizer(0.005).minimize(loss) # 使用梯度下降法,设置步长0.005,来最小化损失

在设置梯度下降算法时,需要人工设置学习率(步长),一般数值都比较小,如果发现无法拟合,可以调小学习率,如果拟合速度过慢,可以调大学习率。

完整代码

下面是完整的实现代码

# 引入tensorflow、numpy和matplotlib库

import tensorflow as tf

import numpy as np

import matplotlib.pyplot as plt

# 获取数据

data = np.genfromtxt('/Users/Bruce/Desktop/PM25.csv', dtype=float, delimiter=',', skip_header=1)

x_ = np.array([x[0] for x in data])[:, np.newaxis]

# 数据归一化

amin, amax = x_.min(), x_.max()

# 求最大最小值

x_data = (x_ - amin)/(amax - amin)

y_data = np.array([y[13] for y in data])[:, np.newaxis]

# 绘图,绘出训练数据

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.scatter(x_data, y_data)

plt.ion()plt.show()

#输入层

xs = tf.placeholder(tf.float32, [None, 1]) #占位符,None表示n*1维矩阵

ys = tf.placeholder(tf.float32, [None, 1]) #占位符,None表示n*1维矩阵

#隐层(200个神经元)

W1 = tf.Variable(tf.random_normal([1,200])) #权重,1*200的矩阵,并用符合正态分布的随机数填充

b1 = tf.Variable(tf.zeros([1,200]) + 0.1) #偏置,1*200的矩阵,使用0.1填充

Wx_plus_b1 = tf.matmul(xs,W1) + b1 #矩阵xs和W1相乘,然后加上偏置

output1 = tf.nn.sigmoid(Wx_plus_b1) #激活函数使用tf.nn.sigmoid

#输出层

W2 = tf.Variable(tf.random_normal([200,1])) #权重,200*1的矩阵,并用符合正态分布的随机数填充

b2 = tf.Variable(tf.zeros([1])+0.1) # 偏置,使用0.1填充

Wx_plus_b2 = tf.matmul(output1,W2) + b2

output2 = Wx_plus_b2 # 输出层不使用激活函数

#损失

loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys-output2),reduction_indices=[1])) #在第一维上,偏差平方后求和,再求平均值,来计算损失

train_step = tf.train.GradientDescentOptimizer(0.005).minimize(loss) # 使用梯度下降法,设置步长0.005,来最小化损失

#初始化

init = tf.global_variables_initializer() #初始化所有变量

sess = tf.Session()

sess.run(init) #变量初始化

#训练

for i in range(5001): #训练10000次

_,loss_value = sess.run([train_step,loss],feed_dict=) #进行梯度下降运算,并计算每一步的损失

if(i%20==0):

print("第%d步,loss_value = %f" % (i,loss_value)) # 每50步输出一次损失

try:

ax.lines.remove(lines[0]) # 在每一次绘图之前先讲上一次绘图删除

except Exception:

pass

lines = ax.plot(x_data, sess.run(output2, feed_dict=), 'r-') plt.pause(0.1)

sess.close()

训练循环总共设置了5001步,每20步打印出当前的损失数值,并且绘制出拟合的曲线样式,运行起来会看到动画的拟合过程,比较直观。

数字极客

公众号ID:digital-geek

关注

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180419G1QDT700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券