线性回归和多项式回归的原始简单实现

  • 综述
  • 原理介绍
  • 代码实现
  • 线性回归
  • 多项式回归
  • 总结


综述

本博客主要介绍机器学习算法的基石——线性回归算法,本文章将从简单的原理介绍、代码的实现与分析,总结等几个部分展开。作为一个刚刚入门的相关专业学生,在原理和编程上理解可能不足,写的代码效率和性能也不如调包来的直接高效,但重要原理的实现和基础的巩固,请各位大佬不喜勿喷!谢谢!

原理介绍

线性回归模型的主要作用是对连续数据的特征进行预测,最典型的便是房价的预测模型,基于一些已知的房价数据,拟合出一条曲线(本质上是直线),对下一个将要出现的数据进行预测和分析。
典型的模型表示为 多项式回归算法_线性回归或者更为简单,即为
多项式回归算法_python_02其中,
多项式回归算法_线性回归_03

而模型的优化策略往往是基于损失函数的,可以定义损失函数为绝对值损失函数MAE,
多项式回归算法_机器学习_04
也可以是MSE,均方误差损失函数
多项式回归算法_线性回归_05

有了模型和策略,我们接下来就可以使用相应的算法来对模型的参数多项式回归算法_人工智能_06进行优化,这里我们使用梯度下降法,而梯度下降法的本质即是求导,在此不做过多赘叙,
多项式回归算法_python_07其中,多项式回归算法_人工智能_08为学习率或步长,
多项式回归算法_python_09
其中,多项式回归算法_机器学习_10

而多项式回归本质上其实是线性回归,只是多了一步数据处理工作,将数据处理成多个在多项式回归算法_人工智能_11罢了。

下面看代码:

代码实现

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和更快拟合到梯度的目的。
请各位批评和指正。