版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mr_muli/article/details/81363911
- 参考博客:深入浅出–梯度下降法及其实现
- 参考链接:https://blog.csdn.net/robotcat123/article/details/80588918
- 参考链接:https://www.jianshu.com/p/c7e642877b0e
- 在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率
- 在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向
- 梯度的方向是函数在给定点上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向
- 为什么要梯度要乘以一个负号?
- 梯度前加一个负号,就意味着朝着梯度相反的方向前进!我们在前文提到,梯度的方向实际就是函数在此点上升最快的方向!而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 02 17:01:54 2018
@author: muli
"""
import numpy as np
import matplotlib.pyplot as plt
# Size of the points dataset.
m = 20
# Points x-coordinate and dummy value (x0, x1).
X0 = np.ones((m, 1))
X1 = np.arange(1, m+1).reshape(m, 1)
#X1 = np.zeros((m, 1))
# 将两个向量,水平拓展
X = np.hstack((X0, X1))
# Points y-coordinate
y = np.array([
3, 4, 5, 5, 2, 4, 7, 8, 11, 8, 12,
11, 13, 13, 16, 17, 18, 17, 19, 21
]).reshape(m, 1)
# 学习率
alpha = 0.01
# 定义均方误差代价函数
def error_function(theta, X, y):
'''Error function J definition.'''
diff = np.dot(X, theta) - y
# 转置相乘diff'*diff
return (1./2*m) * np.dot(np.transpose(diff), diff)
# 梯度下降函数,对代价函数求偏导即可
def gradient_function(theta, X, y):
'''Gradient of the function J definition.'''
diff = np.dot(X, theta) - y
# 转置相乘 X'*diff
return (1./m) * np.dot(np.transpose(X), diff)
# 梯度下降
def gradient_descent(X, y, alpha):
'''Perform gradient descent.'''
# theta:定义的系数
theta = np.array([1, 1]).reshape(2, 1)
gradient = gradient_function(theta, X, y)
# 终止条件
# 当梯度小于1e-5时,说明已经进入了比较平滑的状态,
# 类似于山谷的状态,这时候再继续迭代效果也不大了,
# 所以这个时候可以退出循环!
while not np.all(np.absolute(gradient) <= 1e-5):
theta = theta - alpha * gradient
gradient = gradient_function(theta, X, y)
return theta
optimal = gradient_descent(X, y, alpha)
print('optimal::', optimal)
print('error function:', error_function(optimal, X, y)[0,0])
fig = plt.figure()
ax1 = fig.add_subplot(111)
#设置标题
ax1.set_title('Scatter Plot')
#设置X轴标签
plt.xlabel('X')
#设置Y轴标签
plt.ylabel('Y')
#画散点图
# X原始图
for i in range(0,20):
ax1.scatter(X[i,0],X[i,1],c = 'r',marker = 'o')
# y的实际图
for n in range(1,21):
ax1.scatter(n,y[n-1],c = 'b',marker = 'x')
# 获取的theta值
theta=optimal
y1=np.dot(X, theta)
print(y1)
# 拟合图
for n in range(1,21):
ax1.scatter(n,y1[n-1],c = 'g',marker = 'v')
#设置图标
plt.legend('x1')
#显示所画的图
plt.show()
- 效果图:
- 理解及计算过程: