【机器学习笔记1.4】用tensorflow矩阵思想做线性回归

先生成样本数据

参照【tensorflow ML笔记1.1】,这里用矩阵的思想对其进行改进。另外这里将生成的数据保存成txt文件,在后面都将使用这个文件里的样本数据来分析比较批量梯度下降和随机梯度下降的区别。
【例1】

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

n = 100
# 产生n维标准正太分布随机数
x_data = np.random.randn(n)  #[2]
# 我们假设模型为 y = 0.3x + 0.15,这里还要为其添加均值为0.0、标准差为0.05的服从正太(高斯)分布、维度为n的噪声
y_data = x_data * 0.3 + 0.15 + np.random.normal(0.0, 0.05, n)

# 将样本数据存储起来,便于在下次使用相同的样本数据进行分析
np.savetxt('x_data.txt', x_data)
np.savetxt('y_data.txt', y_data)

# 画出原数据散点图
plt.plot(x_data, y_data, 'ro', label='Original data')
plt.legend()
plt.show()

批量梯度下降

将原数据x_data、y_data表示成矩阵的形式。

X_data = np.ones([n, 2])
X_data[:, 0] = x_data
Y_data = np.ones([n, 1])
Y_data[:, 0] = y_data

注意:
x_data.shape = (n, ),
X_data.shape = (n, 2),
y_data.shape = (n, ),
Y_data.shape = (n, 1)

weight、bias可分别看做为weight1、weight2,于是有矩阵 $
\vec{w} =
\left[ \begin{array}{ccc}
weight1 \
weight2 \end{array} \right]$,对应tensorflow代码如下:

weight = tf.Variable(np.ones([2, 1]), dtype=tf.float64)

对应的加减乘除运算应该改为用tensorflow中的特有函数来运算。

y_model = tf.matmul(X_data, weight)
loss = tf.reduce_mean(tf.pow(tf.subtract(y_model, Y_data), 2))

注意:tf.pow(…)此时返回的是一个n*1的矩阵,这里要用tf.reduce_mean求其均值作为loss值。为什么要用均值作为loss值?这已经在【tensorflow ML笔记1.1】也有所提及。

本节为了比较批量梯度下降和随机梯度下降的差异性,因此下面代码均绘制了loss曲线。

完整代码如下:
【接例1】

X_data = np.ones([n, 2])
X_data[:, 0] = x_data
Y_data = np.ones([n, 1])
Y_data[:, 0] = y_data

weight = tf.Variable(np.ones([2, 1]), dtype=tf.float64)
y_model = tf.matmul(X_data, weight)

loss = tf.reduce_mean(tf.pow(tf.subtract(y_model, Y_data), 2))
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

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

loss_buf = []
for _ in range(500):
    sess.run(train_op)

    loss_val = sess.run(loss)
    print('loss_val = ', loss_val)
    loss_buf.append(loss_val)
    print('weight = ', weight.eval(sess))

loss_ndarray = np.array(loss_buf)
loss_size = np.arange(len(loss_ndarray))

plt.subplot(221)
plt.plot(x_data, y_data, 'ro', label='Original data')
plt.subplot(222)
plt.plot(x_data, y_data, 'ro', label='Original data')
#plt.plot(x_data, sess.run(y_model), label='Fitted line') # OK
plt.plot(x_data, np.dot(X_data, sess.run(weight)), label='Fitted line')
plt.legend()
plt.subplot(212)
plt.plot(loss_size, loss_ndarray, 'b*', label='loss')
plt.legend()
plt.show()

最后的loss值和weight值分别如下:
loss_val = 0.0027017296928188513
weight = [[0.30396377]
[0.14671045]]
0.00396377
0.00328955
拟合效果和loss曲线如下:
enter image description here

这里说明一下,其实也可以用喂数据的方式进行批量梯度下降,代码如下:

sess.run(train_op, feed_dict={X_hold: X_data, Y_hold: Y_data})
loss_val = sess.run(loss, feed_dict={X_hold: X_data, Y_hold: Y_data})

随机梯度下降

对上述程序稍作改变即可。
定义占位符作为数据输入:

X_hold = tf.placeholder(tf.float64, [None, 2])
Y_hold = tf.placeholder(tf.float64, [None, 1])

# weight和上述代码一样,仍然是shape为(2, 1)的tf.Variable
weight = tf.Variable(np.ones([2, 1]), dtype=tf.float64)
y_model = tf.matmul(X_hold, weight)
loss = tf.reduce_mean(tf.pow(tf.subtract(y_model, Y_hold), 2))

相应的迭代方式也要发生改变:

for (x, y) in zip(X_data, Y_data):
    x = x.reshape([1, 2])
    y = y.reshape([1, 1])
    sess.run(train_op, feed_dict={X_hold:x, Y_hold:y})

完整代码如下:
【例2】

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

# 为了便于比较批量梯度下降和随机梯度下降的效果,这里用与上例相同的数据作为此次训练的样本。
x_data = np.loadtxt('x_data.txt')
y_data = np.loadtxt('y_data.txt')
n = x_data.shape[0]

# 画出原数据散点图
plt.plot(x_data, y_data, 'ro', label='Original data')
plt.legend()
plt.show()

X_data = np.ones([n, 2])
X_data[:, 0] = x_data
Y_data = np.ones([n, 1])
Y_data[:, 0] = y_data

threshold = 1.0e-2
X_hold = tf.placeholder(tf.float64, [None, 2])
Y_hold = tf.placeholder(tf.float64, [None, 1])
weight = tf.Variable(np.ones([2, 1]), dtype=tf.float64)
y_model = tf.matmul(X_hold, weight)

loss = tf.reduce_mean(tf.pow(tf.subtract(y_model, Y_hold), 2))
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

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

loss_buf = []
for _ in range(300):
    # 随机梯度下降:每次只喂一对(x,y)数据。
    # 注意:这里随机梯度下降并没有做到每轮循环都是随机的。
    for (x, y) in zip(X_data, Y_data):
        x = x.reshape([1, 2])
        y = y.reshape([1, 1])
        sess.run(train_op, feed_dict={X_hold:x, Y_hold:y})
    
    # 用每轮循环的最后一对数据计算loss值。
    loss_val = sess.run(loss, feed_dict={X_hold: x, Y_hold: y})

    print(loss_val)
    loss_buf.append(loss_val)
    if loss_val <= threshold:
        flag = 0
    print(weight.eval(sess))

loss_ndarray = np.array(loss_buf)
loss_size = np.arange(len(loss_ndarray))

plt.subplot(221)
plt.plot(x_data, y_data, 'ro', label='Original data')
plt.subplot(222)
plt.plot(x_data, y_data, 'ro', label='Original data')
#plt.plot(x_data, sess.run(y_model), label='Fitted line') # OK
plt.plot(x_data, np.dot(X_data, sess.run(weight)), label='Fitted line')
plt.legend()
plt.subplot(212)
plt.plot(loss_size, loss_ndarray, 'b+', label='loss')
plt.legend()
plt.show()

最后的loss值和weight值分别如下:
loss_val = 0.0022543945880998794
weight = [[0.31139591]
[0.15151023]]
0.01139591
0.00151023
拟合效果和loss曲线如下:
enter image description here

批量梯度下降占用内存大,迭代一轮所有数据运算速度快,收敛所需迭代轮数较多;
随机梯度下降占用内存小,迭代一轮所有数据运算速度慢,收敛所需迭代轮数较少。
至于两者的精度比较的话,本文的数据量可能还不够,这个暂且留待后续再作比较。

补充说明

事实上,上述两种方式都不够完美,在实际应用中一般是结合上述两种方法,即在随机梯度下降时,每次喂小批量的数据,我们称之为mini_batch梯度下降法。这一点在文献[1.11.2]也有提及:还有一种方法叫做mini_batch梯度下降法,即选择一个规模较小的数据集进行梯度下降计算。

参考文献

[1] 王晓华. TensorFlow深度学习应用实践

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值