python -V 3.6,需要numpy和matplotlib库
机器学习用于回归分析
用于回归分析,回归就是预测数据为连续性数值。
这里,就举一个一元线性回归,也就是 y = k ∗ a + b y = k * a + b y=k∗a+b
损失函数和最小二乘法
这里就要介绍
c
o
s
t
f
u
n
c
t
i
o
n
cost function
costfunction,可以叫它损失函数,也可以叫它代价函数,用于回归分析,这里可以采用最小二乘法作为损失函数。
最小二乘法简单点说就是求误差平方和。
求损失函数
假设一堆数据中,一个点 x x x的真实值为 y y y,预测值为 h ( x ) h(x) h(x),那么误差平方就为 ( h ( x ) − y ) 2 (h(x)-y)^2 (h(x)−y)2,这只是一个点 x x x,那么所有的 x x x范围内的误差平方和就为:
J ( k , b ) = ( 1 / 2 m ) ∗ ∑ i = 1 m ( h ( x ) − y ) 2 J(k,b)=(1/2m) * \sum_{i=1}^{m} (h(x)-y)^2 J(k,b)=(1/2m)∗∑i=1m(h(x)−y)2
上面这个函数,也就是损失函数。
现在的目标,就是利用梯度下降法,不断优化,迭代,使得 J ( k , b ) J(k,b) J(k,b)达到一个全局最小值或局部最小值。 J ( k , b ) J(k,b) J(k,b)就是关于 k , b k,b k,b的函数,所以就是迭代 k 和 b k和b k和b的值。
关于梯度下降法的概念,简单的理解,就是求导。
损失函数迭代的过程
J ( k , b ) = ( 1 / 2 m ) ∗ ∑ i = 1 m ( h ( x ) − y ) 2 J(k,b)=(1/2m) * \sum_{i=1}^{m} (h(x)-y)^2 J(k,b)=(1/2m)∗∑i=1m(h(x)−y)2
首先对 k k k求导:
k . g r a d = ( 1 / m ) ∗ ∑ i = 1 m ( h ( x ) − y ) k.grad= (1/m) * \sum_{i=1}^{m} (h(x)-y) k.grad=(1/m)∗∑i=1m(h(x)−y)
然后对 b b b求导:
b . g r a d = ( 1 / m ) ∗ ∑ i = 1 m ( h ( x ) − y ) ∗ x b.grad= (1/m) * \sum_{i=1}^{m} (h(x)-y)*x b.grad=(1/m)∗∑i=1m(h(x)−y)∗x
上面 k . g r a d 和 b . g r a d k.grad和b.grad k.grad和b.grad就是迭代一次后的 k 和 b 值 k和b值 k和b值。
因为要迭代到损失函数达到全局最小值,所以这里引入了一个学习率 l r lr lr的概念,简单的理解,就是每次迭代的学习程度。
代码表示迭代一次后的 k 和 b 值 k和b值 k和b值为:
k = k − l r ∗ ( 1 / m ) ∗ ∑ i = 1 m ( h ( x ) − y ) k= k - lr * (1/m) * \sum_{i=1}^{m} (h(x)-y) k=k−lr∗(1/m)∗∑i=1m(h(x)−y)
b = b − l r ∗ ( 1 / m ) ∗ ∑ i = 1 m ( h ( x ) − y ) ∗ x b= b - lr * (1/m) * \sum_{i=1}^{m} (h(x)-y)*x b=b−lr∗(1/m)∗∑i=1m(h(x)−y)∗x
上面公式中的 l r lr lr就是自定义的学习率。
代码
import numpy as np
import matplotlib.pyplot as plt
# 生成假数据
xdata = np.ones((100, 2)) # 生成100x2的矩阵
for i in range(100):
xdata[i, 1] = np.random.random()
# print(xdata)
ydata = np.zeros((100, 1))
for k in range(100):
random1 = np.random.random()
# print(random1)
ydata[k, 0] = 2 * xdata[k, 1] + random1
# print(ydata)
xdata = xdata[:, 1]
# plt.scatter(xdata, ydata)
# plt.show()
# 学习率 learning rate
lr = 0.8
# 截距
b = 0
# 斜率
k = 0
# 最大迭代次数
epochs = 100
# 最小二乘法
def compute_error(b, k, xdatata, ydata):
totalError = 0
for i in range(0, len(xdata)):
totalError += (ydata[i] - (k * xdata[i] + b)) ** 2
return totalError / float(len(xdata))
# 梯度下降
def gradient_descent_runner(xdata, ydata, b, k, lr, epochs):
# 计算总数据量
m = float(len(xdata))
# 循环epochs次
for i in range(epochs):
b_grad = 0
k_grad = 0
# 计算梯度的总和再求平均
for j in range(0, len(xdata)):
b_grad += (1 / m) * ((k * xdata[j] + b) - ydata[j])
k_grad += (1 / m) * xdata[j] * (((k * xdata[j]) + b) - ydata[j])
# 更新b和k
b = b - (lr * b_grad)
k = k - (lr * k_grad)
# 每迭代5次,输出一次图像
if i % 5 == 0:
print('epochs:', i)
plt.cla()
plt.plot(xdata, ydata, 'b.')
plt.plot(xdata, k * xdata + b, 'r')
# plt.show()
plt.pause(0.1)
return b, k
print('Starting b = {}, k = {},error = {}'.format(b,k,compute_error(b,k,xdata,ydata)))
print('Running...')
b, k = gradient_descent_runner(xdata,ydata,b,k,lr,epochs)
print('After {0} iterations b = {1},k={2},error = {3}'.format(epochs,b,k,compute_error(b,k,xdata,ydata)))
# 画图
plt.ion()
plt.plot(xdata,ydata,'b.')
plt.plot(xdata,k*xdata+b, 'r-')
plt.ioff()
plt.show()