机器学习基础算法三:线性回归算法实验(梯度下降法)

线性回归算法实验(梯度下降法)

一、前期准备

  • 数据的数量级如果相差太大是不适合梯度下降算法的。(需要进行处理,要把它们变成相同的数量级)

二、梯度下降法简介。

  • 顾名思义,梯度下降法的计算过程就是沿梯度下降的方向求解极小值(也可以沿梯度上升方向求解极大值)。
    其迭代公式为 a k + 1 = a k + ρ k − ( k ) a_{k+1}=a_{k}+ \rho_{k^{-(k)}} ak+1=ak+ρk(k) ,其中 代表梯度负方向, 表示梯度方向上的搜索步长。梯度方向我们可以通过对函数求导得到,步长的确定比较麻烦,太大了的话可能会发散,太小收敛速度又太慢。一般确定步长的方法是由线性搜索算法来确定,即把下一个点的坐标看做是ak+1的函数,然后求满足f(ak+1)的最小值的ak+1即可。
    因为一般情况下,梯度向量为0的话说明是到了一个极值点,此时梯度的幅值也为0.而采用梯度下降算法进行最优化求解时,算法迭代的终止条件是梯度向量的幅值接近0即可,可以设置个非常小的常数阈值。

三、完整代码

import numpy as np
import pandas as pd
from sklearn.datasets import load_boston

# 增加表格的列数行数和每行的宽度以此让数据集完整表示
pd.set_option('display.max_rows', 1000)
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)

# 将sklearn数据集转换为csv
if __name__ == '__main__':
    boston = load_boston()
    data = pd.DataFrame(boston.data, columns=boston.feature_names)
    data['MEDV'] = boston['target']
    data.to_csv('./boston.csv', index=None)


class LinearRegression:
    """使用Python语言实现线性回归算法。(梯度下降)"""

    def __init__(self, alpha, times):
        """初始化方法。
        :parameter
        alpha:float
            学习率。用来控制步长。(权重调整的幅度)

        times :int
            循环迭代的次数。
        """

        self.alpha = alpha
        self.times = times

    def fit(self, X, y):
        """根据提供的训练数据X,对模型进行训练。
        :parameter
        X:类数组类型。形状:[样本数量,特征数量]
            带训练的样本特征属性。(特征矩阵)

        y:类数组类型,形状:[样本数量]
            目标值(标签信息)。
        """

        X = np.asarray(X)
        y = np.asarray(y)
        # 创建权重的向量,初始值为0(或任何其他的值),长度比特征数量多1。(多出的一个值就是截距)
        self.w_ = np.zeros(1 + X.shape[1])
        # 创建损失列表,用来保存每次迭代后的损失值。损失值计算:(预测值 - 真实值)的平方和除以2
        self.loss_ = []

        # 进行循环,多次迭代在每次迭代过程中,不断去调整全总值使得损失值不断减小。
        for i in range(self.times):
            # 计算预测值
            y_hat = np.dot(X, self.w_[1:])+self.w_[0]
            # 计算真实值与预测值之间的差距。
            error = y-y_hat
            # 将损失值加入到损失列表当中
            self.loss_.append(np.sum(error ** 2) / 2)
            # 根据差距调整权重w_,根据公式:调整为 权重(j)=权重(j)+ 学习率*sum((y-y_hat)*x(j))
            self.w_[0] += self.alpha * np.sum(error)
            self.w_[1:] += self.alpha * np.dot(X.T, error)


    def predict(self, X):
        """根据参数传递的样本,对样本数据进行预测。
        :parameter
        X:类数组类型,形状:[样本数量,特征数量]
            待测试的样本。
        :returns
        result:数组类型。
            预测的结果。
        """
        X = np.asarray(X)
        result = np.dot(X, self.w_[1:])+self.w_[0]
        return result


lr = LinearRegression(alpha=0.001, times=20)
t = data.sample(len(data), random_state=0)
train_X = t.iloc[:400, :-1]
train_y = t.iloc[:400, -1]
test_X = t.iloc[400:, :-1]
test_y = t.iloc[400:, -1]

lr.fit(train_X,train_y)
result = lr.predict(test_X)
# print(np.mean((result - test_y) ** 2))
# print(lr.w_)

class StandardScaler:
    """该类对数据进行标准化处理。"""

    def fit(self, X):
        """根据传递的样本,计算每个特征列的均值与标准差。
        :parameter
        X:类数组类型
            训练数据,用来计算均值与标准差。
        """
        X = np.asarray(X)
        self.std_ = np.std(X, axis=0)
        self.mean_ = np.mean(X, axis=0)

    def transform(self, X):
        """对给定的数据X进行标准化处理。(将X的每一列都变成标准正态分布的数据)
        :parameter
        X: 类数组类型
            待转换的数据。
        :returns
        result:类数组类型。
            参数X转换成标准正态分布后的结果。
        """

        return(X-self.mean_)/self.std_

    def fit_transform(self, X):
        """对数据进行训练,并转换,返回转换之后的结果。
        :parameter
        X:类数组类型
            待转换的数据

        :returns
        result:类数组类型
            参数X转换成标准正态分布后的结果。
        """
        self.fit(X)
        return self.transform(X)

# 为了避免每个特征数量级的不同,从而在梯度下降的过程中带来影响。
# 我们现在对每个特征进行标准化处理
lr = LinearRegression(alpha=0.0005,times=20)
t = data.sample(len(data), random_state=0)
train_X = t.iloc[:400, :-1]
train_y = t.iloc[:400, -1]
test_X = t.iloc[400:, :-1]
test_y = t.iloc[400:, -1]

# 对数据进行标准化处理
s = StandardScaler()
train_X = s.fit_transform(train_X)
test_X = s.fit_transform(test_X)

s2 = StandardScaler()
train_y = s.fit_transform(train_y)
test_y = s.fit_transform(test_y)

lr.fit(train_X, train_y)
result = lr.predict(test_X)
print(np.mean((result - test_y) ** 2))
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值