自己动手做ML算法系列(1)– Gradient Descent

本文通过Python实现梯度下降法解决线性回归问题,并利用matplotlib可视化每轮迭代过程中的参数变化,以此观察算法的收敛过程。

自己动手做ML算法系列(1)– Gradient Descent

Gradient Descent大家都很熟悉了, 这个学习笔记记录我的一次尝试。 语言:python, 用到的包: numpy

直接上代码:

import numpy as np

X_train = np.array([[1, 6], [1, 8], [1, 10], [1, 14], [1, 18]])
y_train = np.array([[7], [9], [13], [17.5], [18]])
X_test = np.array([[1, 6], [1, 8], [1, 11], [1, 16]])
y_test = np.array([[8], [12], [15], [18]])

w = 2*np.random.random(2) - 1

np.random.seed(1)

alpha = 0.01

for iter in xrange(100000):
    # Stochastic Gradient Descent: pick an instance
    i = np.random.randint(5)
#     print 'picking i:', i

    l = np.dot(w, X_train[i])
#     print 'dot product is: ', l

    l_error = y_train[i][0] - l
#     print 'error is: ', l_error

    l_delta = alpha * l_error * X_train[i]
#     print 'delta is: ', l_error

    w += l_delta
#     print 'w is:', w

print 'Test:', np.dot(w, X_test[0])
结果:
Test: 6.88059010909

原值是8, 我们的输出是6.88, 可以说还是有不少误差。
我想,如果让我们把整个过程画出来,我们可能会更清楚它具体是如何收敛的。

为了取得中间值, 我们需要创造一个np.array来储存每次更新前后的w值

代码如下:

import numpy as np

X_train = np.array([[1, 6], [1, 8], [1, 10], [1, 14], [1, 18]])
y_train = np.array([[7], [9], [13], [17.5], [18]])
X_test = np.array([[1, 6], [1, 8], [1, 11], [1, 16]])
y_test = np.array([[8], [12], [15], [18]])

w = 2*np.random.random(2) - 1

np.random.seed(1)

alpha = 0.01

store_w = []  # 用来储存中间的w

for iter in xrange(5000):
    # Stochastic Gradient Descent: pick an instance
    i = np.random.randint(5)
#     print 'picking i:', i

    l = np.dot(w, X_train[i])
#     print 'dot product is: ', l

    l_error = y_train[i][0] - l
#     print 'error is: ', l_error

    l_delta = alpha * l_error * X_train[i]
#     print 'delta is: ', l_error

    store_w.append(w.copy())
    w += l_delta
#     print 'w is:', w

print 'Test:', np.dot(w, X_test[0])

%matplotlib notebook
import matplotlib.pyplot as plt

plt.figure()

tmp = []
for i in xrange(0,len(store_w),20):  #每隔20次更新才取值,这样效果比较明显,并且减少内存消耗
    tmp.append(store_w[i])
store_w = tmp

w_0s = [i[0] for i in store_w]  # 取出w的第一项, 作为横坐标
w_1s = [i[1] for i in store_w]  # 取出w的第二项,作为纵坐标

plt.plot(w_0s, w_1s)
plt.scatter(w_0s, w_1s, c='r', edgecolors='None')

plt.show()

出图:
这里写图片描述

能发现虽然它收敛得比较混乱,但是最后还是稳定到了一个特定区间。


从准确性的角度来观测收敛情况

我选取一个特定的样本, 在同一张图上画出每次更新后预测值和样本值
这里写图片描述

中间的黑线表示样本值,横坐标表示更新次数
虽然不太知道中间发生了什么(笑),不过好歹收敛了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值