转载自:线性回归与非线性回归:1.0一元线性回归与代价函数(损失函数)
- 回归分析:用来建立方程模拟两个或者多个变量之间如何关联
- 因变量:被预测的变量(结果/标签),输出
- 自变量:被用来进行预测的变量(特征),输入
- 一元线性回归:包含一个自变量与一个因变量,并且变量的关系用一条直线来模拟
一元线性回归
公式:(h_ heta = heta_0+ heta_1x)
方程对应的图像是一条直线,称作回归线。其中( heta_1)为回归线的斜率,( heta_0)为回归的截距。
相关性:$$ egin{cases} 正相关: heta_1>0 不相关: heta_1 = 0 负相关: heta_1<0 end{cases}$$
代价函数
一般使用最小二乘法,真实值(y),预测值(h_ heta(x)),则误差平方为((y-h_ heta(x))^2),找到合适的参数,使得误差平方平方和最小$$J( heta_0 , heta_1) = frac{1}{2m}sum_{i=1}^m(y-h_ heta(x))^2$$
其中共有m个样本点,乘以1/2是为了方便计算,如求导。
相关系数
定义:相关关系是一种非确定性的关系,相关系数是研究变量之间线性相关程度的量。
线性相关:在向量空间V的一组向量:(A:alpha_1,alpha_2,ldotsalpha_m),如果存在不全为零的数(k_1,k_2,ldots k_m),使$$k_1alpha_1+k_2alpha_2+cdots k_malpha_m = O$$则称向量组A是线性相关的,否则(k_1,k_2,ldots k_m)全为0,称其为线性无关的。
公式:$$r_{xy} = frac{sum (x_i - overline x)(y_i - overline y)}{sqrt{sum (x_i - overline x)^2sum(y_i - overline y)^2}} = frac{cov(x,y)}{sqrt{var[x]var[y]}}$$
决定系数
定义:相关系数(R^2)是用来描述两个变量之间的线性关系的,但决定系数的适用范围更广,可以用于描述非线性或者有两个及两个以上自变量的相关关系。它可以用来评估模型的效果。
总平方和(SST):(sum_{i=1}^{n}(y_i - overline y)^2)
回归平方和(SSR):(sum_{i=1}^{n}(hat y-overline y)^2)
残差平方和(SSE):(sum_{i=1}^{n}(y_i-hat y)^2)
(y_i)是真实值,(overline y)是真实值的平均值,(hat y)是预测值。
它们三者的关系是:(SST=SSR+SSE)
决定系数:(R^2 = frac{SSR}{SST} = 1-frac{SSE}{SST})
用梯度下降法求解线性回归
一元线性回归方程:(h_ heta = heta_0+ heta_1x)
参数:( heta_0),( heta_1)
代价函数:(J( heta_0 , heta_1) = frac{1}{2m}sum_{i=1}^m(y-h_ heta(x))^2)
目标:(min J( heta_0 , heta_1))
梯度下降法:不断改变( heta_0),( heta_1),直到(J( heta_0 , heta_1))达到一个全局最小或者局部最小。$$repeat until convergence{ heta_j:= heta_j - alphafrac{partial}{partial heta_j}J( heta_0, heta_1) } (for j=0 and j=1)$$ (alpha)为学习率,当学习率过大会造成不收敛也就是找不到一个全局最小值或者局部最小值,学习率过小会浪费大量的时间进行计算。
正确的做法:同步更新$$tempt0:= heta_0 - alphafrac{partial}{partial heta_0}J( heta_0, heta_1)$$$$tempt1:= heta_1 - alphafrac{partial}{partial heta_1}J( heta_0, heta_1)$$$$ heta_0:=tempt0$$$$ heta_1:=tempt1$$
使用梯度下降:$$repeat until convergence{ heta_0:= heta_0-alphafrac{1}{m}sum_{i=1}^m(h_ heta(x_i)-y_i) heta_1:= heta_1-alphafrac{1}{m}sum_{i=1}^m(h_ heta(x_i)-y_i)*x_i }$$
实战
import numpy as np
import matplotlib.pyplot as plt
#载入数据
data = np.genfromtxt("data.csv",delimiter=",")#加载文件,分隔符为逗号
x_data = data[:,0]#存储第0列的所有数据
y_data = data[:,1]#存储第1列的所有数据
#学习率
lr = 0.0001
#截距
b = 0.0
#斜率
k = 0.0
#最大迭代次数
epochs = 50
#最小二乘法
def compute_error(b, k, x_data, y_data):
totalError = 0
for i in range(0,len(x_data)):
totalError += (y_data[i] - (k * x_data[i] + b)) ** 2
return totalError / float(len(x_data)) / 2.0
#梯度下降法求最小值
def gradient_descent_runner(x_data, y_data, b, k, lr, epochs):
#计算总数据量
m = len(x_data)
#循环epochs次
for i in range(epochs):
b_grade = 0
k_grade = 0
#计算梯度总和在求平均
for j in range(0, len(x_data)):
b_grade += -(1/m) * (y_data[j] - (k * x_data[j] + b))
k_grade += -(1/m) * (y_data[j] - (k * x_data[j] + b)) * x_data[j]
#更新学习率
b = b - (lr * b_grade)
k = k - (lr * k_grade)
return b,k
print("Starting b = {0}, k = {1}, error = {2}".format(b, k, compute_error(b, k, x_data, y_data)))
print("Running...")
b,k = gradient_descent_runner(x_data, y_data, b, k, lr, epochs)
print("After {0} iterations b = {1}, k = {2}, error = {3}".format(epochs, b, k, compute_error(b, k, x_data, y_data)))
#画图
plt.plot(x_data, y_data, 'b.')
plt.plot(x_data, k*x_data+b, 'r')
plt.show()