线性回归(最小二乘法and梯度下降)

线性回归module封装

两个类分别实现最小二乘法及梯度下降拟法拟合

import numpy as np

#最小二乘法拟合
class OSLlinearregression:

    def _ols(self, x, y):
        '''最小二乘法估计w'''
        return np.linalg.pinv((x.T).dot(x)).dot(x.T).dot(y)


    def preprocess_data_X(self, X):
        '''数据预处理,扩展X 第一列为1'''
        m, n = X.shape
        tmp = np.ones(m).reshape(-1,1)
        X_ = np.hstack([tmp, X])    #将全1列 放到第一列
        return X_


    def train(self, X_train, Y_train):
        '''训练模型'''
        X_train = self.preprocess_data_X(X_train)
        self.w = self._ols(X_train, Y_train)


    def predict(self, X):
        X = self.preprocess_data_X(X)
        return np.matmul(X, self.w)


# 梯度下降算法拟合
class GDLinearRegression():

    def __init__(self, n_iter = 20, eta = 1e-3, tol = None):
        '''模型参数初始化'''
        self.n_iter = n_iter   # 迭代次数
        self.eta = eta         # 学习率
        self.tol = tol         # 误差变化阈值
        self.w = None          # 模型参数w

    def _loss(self, y, y_pred):
        '''计算损失值'''
        return np.sum((y_pred - y)**2) /(2 * y.size)
    
    def _gradient(self, X, y, y_pred):
        '''计算梯度'''
        return np.dot(y_pred - y, X) /y.size
    
    def _predict(self, X, w):
        '''内部接口,即为假设函数H(x)'''
        return np.dot(X, w)
    
    def preprocess_data_X(self, X):
        '''数据预处理,添加全1列到首列'''
        m, n = X.shape
        temp = np.ones(m).reshape(m,1)
        X_ = np.hstack([temp, X])
        return X_

    def _gradient_dexcent(self, w, X, y):
        '''梯度下降算法'''
        # 若指定tol 则启用早期停止法
        if self.tol is not None:
            loss_old = np.inf  # np.inf 表示无穷大
        #用梯度下降算法,最多迭代n_iter次
        for step_i in range(self.n_iter):
            y_pred = self._predict(X, w)
            loss = self._loss(y,y_pred)
            print(str(step_i) + 'Loss:' + str(loss) )

            #早期停滞法
            if self.tol is not None:
                #如果当前损失值下降小于阈值,则停止迭代
                if (loss_old - loss) < self.tol:
                    break
                loss_old = loss
            
            grad = self._gradient(X, y, y_pred)
            w = w - self.eta * grad
        
    def train(self, X_train, Y_train):
        X_train = self.preprocess_data_X(X_train)
        m, n = X_train.shape
        self.w = np.random.random(n) * 0.05
        self._gradient_dexcent(self.w, X_train, Y_train)

    def predict(self,X):
        X = self.preprocess_data_X(X)
        return np.dot(X,self.w)

线性回归的实战项目

使用以上的OLSLinearRegression和GDLinearRegression预测红酒口感。
数据集下载地址
在这里插入图片描述
数据集中包含1599条数据,其中每一行包含红酒的11个化学特征以及专家评定的口感值。虽然口感值只是3~8的整数,但我们依然把该问题当作回归问题处理,而不是当作包含6种类别(3~8)的分类问题处理。如果当作分类问题,则预测出的类别间无法比较好坏,例如我们不清楚第1类口感是否比第5类口感好,但我们明确知道5.3比4.8口感好。

import numpy as np
from linear_regression import GDLinearRegression, OSLlinearregression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error

#调用Numpy的genfromtxt函数加载数据集
data = np.genfromtxt('winequality-red.csv', delimiter=';', skip_header=True)
#将原始数据X、Y分开
X = data[:,:-1]
y = data[:,-1]
# 对数据集进行切割 切割为训练集、测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.4)


# 创建OSL模型并训练
ols_lr = OSLlinearregression()
ols_lr.train(X_train, y_train)
# 利用拟合出的模型计算测试集的预测值
y_osl_pred =ols_lr.predict(X_test)
# 调用sklearn中的算法计算均方误差
mse = mean_squared_error(y_test, y_osl_pred)
print('最小二乘法拟合结果:')
print('均方误差为:'+str(mse))
# 调用sklearn中的算法计算平均绝对误差
mae = mean_absolute_error(y_test, y_osl_pred)
print('平均绝对误差:'+str(mae))

# 创建GD模型并训练
gd_lr = GDLinearRegression(n_iter=500, eta=0.01)
gd_lr.train(X_train, y_train)
# 利用拟合出的模型计算测试集的预测值
y_gd_pred =gd_lr.predict(X_test)
# 调用sklearn中的算法计算均方误差
mse = mean_squared_error(y_test, y_gd_pred)
print('梯度下降拟合结果')
print('均方误差为:'+str(mse))
# 调用sklearn中的算法计算平均绝对误差
mae = mean_absolute_error(y_test, y_gd_pred)
print('平均绝对误差:'+str(mae))
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值