【001】Python实现,单一变量的线性回归问题
目录
在下自我介绍
本文讲述 单一变量的直线回归!!!!!!
Hello,你们可以叫我弛仔,这算是人生中第一篇正式的分享博客。我呢是大一的学生,对机器学习(Machine Learning)感兴趣。
hhh,也是刚刚接触这方面的学习,想在这里分享初学者的经验,并且给出一些踩过的坑。
还有,我不是大佬哈!!!欢迎各位跟我一起学习!!!
最终的回归结果!
一些概念
拟合是什么?
在我看来,拟合就是把平面上一系列的点,用一条光滑的曲线连接起来。
因为点很复杂,我们可以用各种函数去组合来达到我们的目的。
泛化能力是什么?
训练集在训练后,能够预测位置数据的能力。
简单的了解下即可。
过拟合是什么?
过拟合,可能我们选择模型时过于复杂,在训练时表现极好,实战却不行了~
欠拟合是什么?
与过拟合相反,即训练时的效果就不佳~那就更不要说实战拉!
线性回归
假设函数(hypothesis)
假设函数(Hypothesis),这个函数可以是简单的直线,也可以是复杂的多项式组合。(我认为他就是数学模型,可能不对,若有出入望指正)
代价函数(cost function)
我的图应该很形象的解释了他的意义了吧?我们可以由此计算出所有点的预测值y 与 假设函数h(x)的差,通过平方(平方是为了化负为正)后取均值再除以2,吴恩达老师的课程上就是这么讲哒,通常下除以2,为了能更进一步的将代价最小化吧??
线性回归目标(Goal)
我们的目标:为了让预测值与函数值的误差最小化
即 minimizeJ(theta)
所以引入了梯度下降(Gradient Descent)
梯度下降也可以简单理解,多维也使很好理解的,我先再次梳理下最基础的梯度下降
这只是举了个例子,对J函数求导后,我们发现局部上,导数永远指向最小值处。
所以有了梯度下降的公式:
这需要用到高数中的偏导知识,如果你已经学过导数,那么偏导也是很简单的~
具体推导过程,可以自己动手算一算!
上代码
import sklearn as sk
"""
单变量的线性回归基础
单变量:一个特征哈!!!
"""
from sklearn.datasets import load_boston
import numpy as np
#输出数据的结构
def print_data(data):
print("Shape:",data.shape,"\n")
print("Feature:",data['feature_names'], "\n")
print("Keys:",data.keys(), "\n")
"""
# 计算CostFunction 代价函数
# X为特征矩阵
# y为目标
# theta为theta系数 1 X n 的矩阵
"""
def computerCost(X ,y ,theta):
num = len(y)
y = y.reshape(num,1)
result = np.power((X.dot(theta.transpose()) - y),2)
return np.sum(result) /(2* num)
"""
梯度下降函数
# Param X train Feature
# Param y train Target
# Param theta h(x)=theta(0)+theta(1)*x1
# Param times 迭代的次数
"""
def gridientDescent(X,y,theta,times,learn_rate):
number = len(y) #获取训练数据的数量
X[:,1] = X[:,1]/100 #特征缩放
temp = np.zeros(theta.shape) #用于更新theta
cost = np.zeros(times) #记录每次迭代后代价函数的值
paramters = len(theta[0]) #参数的个数
for i in range(times):
y = y.reshape(number,1)
H = X.dot(theta.transpose())
E = H - y
#print("Y SHAPE:",y.shape)
#print("H SHAPE:",H.shape)
#print("E SHAPE:",E.shape)
for j in range(paramters):#更新theta
XT = X.transpose()
XT = XT[j,:]
XT = XT.reshape(1,len(XT))
#print("XT",XT.shape)
term = XT.dot(E)
temp[0, j] = theta[0, j] - ((1 / number) * learn_rate * term)
theta = temp
print(computerCost(X,y,theta))
return theta
if __name__ == '__main__':
"""
准备好了吗?我们开始操作咯!
# 首先获取我们的数据
"""
Boston = load_boston()
BostonData = Boston.data ##特征数据
BostonTarget = Boston.target ##房价
BostonFeatureName = Boston.feature_names
print(BostonFeatureName)
"""我们使用AGE 这个特征做本次的单特征回归"""
BostonAge = BostonData[:10,6]
BostonAgeTarget = BostonTarget[:10]
print('TARGET SHAPE :',BostonAgeTarget.shape)
print("DATA SHAPE:",BostonAge.shape)
"""发现一共有506条数据,我们获取其中前10行"""
print("DATA:\n",BostonAge)
#给X加入一列,因为theta0 是一个常数项
X = np.column_stack((np.ones(len(BostonAgeTarget)),BostonAge))
theta = np.array([[0,0]]) #参数矩阵
times = 100000 #迭代次数
step = 0.02 #步长
g = gridientDescent(X,BostonAgeTarget,theta,times,step)
"""将数据可视化"""
import matplotlib.pyplot as plt
font = {
'family': 'SimHei',
'weight': 'bold',
'size': '10'
}
plt.rc('font', **font)
plt.rc('axes', unicode_minus=False)
plt.xlabel("Feature Age")
plt.ylabel("House Price")
plt.title("Boston Price Data By Age")
plt.scatter(x=BostonAge,
y=BostonAgeTarget,
c='b',
alpha=.8,
label='训练数据')
#画出拟合直线
x = np.linspace(BostonAge.min(), BostonAge.max(), 100)
f = g[0, 0] + (g[0, 1] * x /100) #注意除以100,因为我们做过特征缩放
plt.plot(x, f, 'r', label='预测函数')
plt.legend(loc=2)
plt.show()
编码中遇到的坑
- 为了每一步都简介明了,代码中加入了很多不必要的中间变量,真正实践的时候不需要这么复杂哦~
- 矩阵的shape,比如读入target y 后,他的shape 是一维的,但是矩阵是二维的,所以会出现无法做运算。
- 尽量输出Shape,通过矩阵运算法则 ,这样可以更快的找到编码可能出错的位置
- 矩阵运算的乘法 * 和 np.dot() 是不同的
- 最后矩阵的求解:这是矩阵哦!!大家用学过的线性代数推导一下就明白拉(提示:由见到推复杂,由一个元素推整个矩阵)
感谢
谢谢大家看完~继续钻研吧!