线性回归和多项式回归的原始简单实现
- 综述
- 原理介绍
- 代码实现
- 线性回归
- 多项式回归
- 总结
综述
本博客主要介绍机器学习算法的基石——线性回归算法,本文章将从简单的原理介绍、代码的实现与分析,总结等几个部分展开。作为一个刚刚入门的相关专业学生,在原理和编程上理解可能不足,写的代码效率和性能也不如调包来的直接高效,但重要原理的实现和基础的巩固,请各位大佬不喜勿喷!谢谢!
原理介绍
线性回归模型的主要作用是对连续数据的特征进行预测,最典型的便是房价的预测模型,基于一些已知的房价数据,拟合出一条曲线(本质上是直线),对下一个将要出现的数据进行预测和分析。
典型的模型表示为 或者更为简单,即为
其中,
而模型的优化策略往往是基于损失函数的,可以定义损失函数为绝对值损失函数MAE,
也可以是MSE,均方误差损失函数
有了模型和策略,我们接下来就可以使用相应的算法来对模型的参数进行优化,这里我们使用梯度下降法,而梯度下降法的本质即是求导,在此不做过多赘叙,
其中,为学习率或步长,
其中,
而多项式回归本质上其实是线性回归,只是多了一步数据处理工作,将数据处理成多个在罢了。
下面看代码:
代码实现
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
#引入本次所需的包
class LinearNeuron:
def __init__(self,in_features):
'''in_features表示输入特征的长度'''
self.in_features = in_features
#初始化参数权值和偏置矩阵
self.W = np.zeros((1,self.in_features),dtype = np.float32)
self.b =0
def predict(self,x):
#构建模型
z = self.W @ x + self.b
return z
def fit(self,X,Y,lr =0.1):
n = X.shape[1] #样本个数
loss0 = np.inf
epslion = 1e-6
#初始化参数权值和偏置矩阵
self.W = np.zeros((1,self.in_features),dtype = np.float32)
self.b =0
iter_value =0
for i in range(n):#因为是小样本预测,优化到样本数据完即可。
#predict
yhat = self.predict(X)#预测值
print(yhat.shape)
e = yhat -Y
# print(e)
loss = np.sum(e**2) / 2*n
print('iter = %3d, error = %.6f'%(iter_value,e.mean()))
iter_value +=1
print('loss_shang = '%(np.abs(loss - loss0)))
if np.abs(loss - loss0) <epslion: #用损失来进行优化
break
loss0 =loss
#delta
#那一堆公式
dW = e@ X.T /n
db = e.mean()
self.W = self.W - dW * lr
self.b = self.b - db*lr
线性回归
#生成随机样本
x = np.random.rand(1,100)*10 - 5 #(-5,5)区间上均匀分布的随机样本x
y = 2*x+1 + np.random.randn(1,100)*0.3 #y=2x+1+noise,噪声满足0均值,标准差为0.3的高斯分布
plt.figure()
plt.scatter(x,y)
plt.show()
#在下面编写代码,使用你编写的神经元模型拟合上面的样本
#设置输入特征长度
eta = 1
#初始化模型
model = LinearNueron(eta)
#训练模型
model.fit(x,y)
#打印数据
print(model.W)
print(model.b)
#在下面编写代码,绘制你拟合的直线
x = np.random.rand(1,100)*10 - 5 #(-5,5)区间上均匀分布的随机样本x
y = 2*x+1 + np.random.randn(1,100)*0.3 #y=2x+1+noise,噪声满足0均值,标准差为0.3的高斯分布
plt.figure()
plt.scatter(x,y)
X = np.linspace(-5,5,num=100)
Y = X *np.mean(model.W[0][0]) + np.mean(model.b)
print(X.shape,Y.shape)
plt.plot(X,Y,color = 'red')
多项式回归
#生成随机样本
x = np.random.rand(1,200)*10 - 5 #(-5,5)区间上均匀分布的随机样本x
y = x**3 + 2*x**2 + x - 1 + np.random.randn(1,200)*0.5 #y=2x+1+noise,噪声满足0均值,标准差为0.5的高斯分
plt.figure()
plt.scatter(x,y)
plt.show()
#在下面把把样本分成训练集和测试集
x_train = x[0,0:150]
y_train = y[0,0:150]
x_test = x[0,150:]
y_test = y[0,150:]
#数据处理
x1 = x_train.copy() ** 3
x2 = x_train.copy() ** 2
X = np.vstack((x1,x2,x_train))
X.shape
#训练模型
My_model = LinearNueron(in_features=3)
My_model.fit(X,y_train,lr=0.00005)
#3.在下面编写代码,计算你训练的模型的训练误差和测试误差(用MSE计算)
y_train_hat = My_model.W @ X + My_model.b
er_train = y_train_hat - y_train
print(er_train)
n = y_train.shape[0]
MSE_train = (error ** 2).sum() / n
print(MSE_train)
x1_test = x_test.copy() ** 3
x2_test = x_test.copy() ** 2
X_test = np.vstack((x1_test,x2_test,x_test))
# X_test_normal = normal(X_test)
# Y_test_normal = normal(y_test)
y_test_hat = My_model.W@X_test + My_model.b
error = y_test - y_test_hat
print(error)
n = y_test.shape[0]
print(n)
MSE_test = (error ** 2).sum() / n
print(MSE_test)
#4.在下面编写代码,绘制你拟合的曲线
#生成随机样本
x = np.random.rand(1,200)*10 - 5 #(-5,5)区间上均匀分布的随机样本x
y = x**3 + 2*x**2 + x - 1 + np.random.randn(1,200)*0.5 #y=2x+1+noise,噪声满足0均值,标准差为0.5的高斯分布
plt.figure()
plt.scatter(x,y)
xs = np.linspace(-5,5,num=100)
ys = My_model.W[0,0]*(xs**3)+My_model.W[0,1]*(xs**2)+My_model.W[0,2]*xs + My_model.b
plt.plot(xs,ys,color = 'red')
总结
经过代码运行和测试后,会发现模型的损失和误差都很大,原因在于生成样本的时候加入了噪声和干扰,可以对样本进行归一化处理来到达优化loss和更快拟合到梯度的目的。
请各位批评和指正。