【线性回归】原生numpy实现波士顿房价预测

系列文章目录

【第一章原理】(109条消息) 【学习笔记】机器学习基础--线性回归_一无是处le的博客-CSDN博客

 【第二章原理】(2条消息) 【学习笔记】机器学习基础--逻辑回归_一无是处le的博客-CSDN博客

 【第三章】传统机器学习【先不写】 

【第四章】聚类算法【先不写

【第五章原理】【学习笔记】深度学习基础----DNN_一无是处le的博客-CSDN博客

【第五章代码实现】【学习笔记】手写神经网络之word2vec_一无是处le的博客-CSDN博客

前言

本章是关于我前一篇学习笔记的代码实现,即根据上一篇的线性回归原理,仅使用numpy自己实现简单的线性回归--波士顿房价预测


一、结构总览

        要实现一个完整的机器学习项目,需要具备以下几个要点:1.获取数据  2.数据预处理  3.构建训练模型  4.训练模型  5.模型评估  6.模型的保存

        而这里我由于我们是仅对上篇文章的代码实现,故而这里的代码会比较简陋,重点内容在于构建训练模型,其他方面则是从简。

二、使用步骤

1.引入库

代码如下:

import numpy as np
from matplotlib import pyplot as plt
from sklearn.datasets import load_boston

2.数据预处理

代码如下:

class StandardScaler:
    def fit(self, X):
        self.mean_ = np.mean(X, axis=0)
        self.std_ = np.std(X, axis=0)

    def transform(self, X):
        return (X - self.mean_) / self.std_

    def fit_transform(self, X):
        self.fit(X)
        return self.transform(X)

数据预处理这里只是简单的使用了数据标准化,如果有需要的话,可以分批并行训练(分batch和epochs)。而标准化则遵循公式:StandardScaler=\frac{x-\mu }{\sigma } (这里\mu表示平均值,就是代码中的mean;\sigma表示方差,就是代码中的std) 

3.构建训练模型

训练模型主要包括损失函数和梯度下降,代码如下:

class GradientDescent:
    def __init__(self, X, y, alpha, epochs):
        self.X = X
        self.y = y
        self.alpha = alpha
        self.epochs = epochs
        self.n = len(y)
        self.theta = np.zeros((X.shape[1], 1))

    def compute_cost(self):
        # @表示矩阵的乘法运算
        predictions = self.X @ self.theta
        # 计算均值误差
        cost = np.sum((predictions - self.y) ** 2) / (2 * self.n)
        return cost

    def gradient_descent(self):
        # 将所有的损失值储存起来,便于做可视化,可以直观的看到损失函数的变化
        cost_history = np.zeros(self.epochs)

        for epoch in range(self.epochs):
            predictions = self.X @ self.theta
            errors = predictions - self.y
            # 计算梯度
            gradient = (self.X.T @ errors) / self.n
            # 更新参数
            self.theta = self.theta - self.alpha * gradient
            cost_history[epoch] = self.compute_cost()

        return self.theta, cost_history

 这段代码是需要我们重点去理解学习的,如果对这些公式不理解的话可以看我的上一篇博客。

        首先是参数(alpha 表示学习率, epoch 表示需要迭代的次数, theta 表示各个特征的权重),至于这里的theta为什么要写成  theta = np.zeros((X.shape[1], 1)  ,因为我们需要对数据集的各个特征进行加权进行训练拟合。如果还不能理解的话直接看官方的参数也能知道我们应该怎么做。这里我们可以看下图数据集的参数量,和使用官方库中训练得出的参数做对比:

 我们可以看到,训练集用的数据中第一个维度的数量为13,再官方库中训练得到的theta参数量,如下图:

可以看到,官方库中的线性回归中的theta的len跟训练集中的第一个维度(也就是特征数)的数量一致,这也就是为什么我们需要这么来设置theta。 

        接下来我们再看下一个难点,也就是我们最需要理解的东西----梯度下降。一般的公式就不多赘述,这里就说说如何求导,也就是为什么   gradient = (self.X.T @ errors) / self.n  。我们先看损失函数微分公式\frac{\partial MSE}{\partial \theta }=\frac{2\sum_{i=1}^{n}(\theta *x-y)}{n}x,而我我们这里设置的error就是θ*x,因此这里self.X.T @ errors(内积)的结果就是\sum_{i=1}^{n}(\theta *x-y)x,有人可能会发现这里多了一个 2 ,这个 2 我将他放在了cost中消除,cost = np.sum((predictions - self.y) ** 2) / (2 * self.n)  原本的损失函数应该是 “/ self.n” 这里这个2就是为了消除微分的影响。

4.训练模型

代码如下:

boston = load_boston()

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(boston.data)

alpha = 0.01
epochs = 1000

X_train, X_test, y_train, y_test = train_test_split(X_train_scaled, boston.target, test_size=0.2, random_state=42)

X_test_scaled = scaler.transform(X_test)

model = GradientDescent(X_train, y_train, alpha, epochs)
final_theta, cost_history = model.gradient_descent()

 这段代码很常规,就不做解释。

5.查看结果,评估模型

代码如下:

# 只看最终的theta值
print('final_theta = ', final_theta[-1])
print('===========================================')
# 只看最后20个损失值
print('cost_history = ', cost_history[-20:])

# 绘图
plt.plot(range(epochs), cost_history)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.title('Gradient Descent Convergence')
plt.show()

 结果如下:

 

 

接下来我们再看看使用官方库来进行波士顿房价预测的结果:

 

        从打印出的结果我们可以看出,我们这次的损失值很大,也就是对模型的拟合性很弱,并且我们可以看到最终训练出来theta有很多很多的数,这其中有绝大多数的是冗余的,或者是噪声之类的,这是由于我没有使用正则化导致的结果,因为我们本篇博客只是对于我上一篇博客的代码解释,而上篇博客中我并没有介绍到相关的正则化这个在我的下一篇博客中会写出【逻辑回归】),因此我们这里不需要看损失值,我们只看最终的绘图,我们可以看到我们的梯度下降是起到了很好的作用,因此我们就可以认为我们较好的完成了我们此次的任务。


总结

        本片博客只是对我上一篇博客的代码解释,有很多方面没有顾及到,因此最终的结果可能会不理想,但是我们还是顺利的完成了我们的基本要求,代码解释,并且其重点梯度下降还是较好的完成了,O(∩_∩)O

完整代码

import numpy as np
from matplotlib import pyplot as plt
from sklearn.datasets import load_boston


class GradientDescent:
    def __init__(self, X, y, alpha, epochs):
        self.X = X
        self.y = y
        self.alpha = alpha
        self.epochs = epochs
        self.n = len(y)
        self.theta = np.zeros((X.shape[1], 1))

    def compute_cost(self):
        predictions = self.X @ self.theta
        cost = np.sum((predictions - self.y) ** 2) / (2 * self.n)
        return cost

    def gradient_descent(self):
        cost_history = np.zeros(self.epochs)

        for epoch in range(self.epochs):
            predictions = self.X @ self.theta
            errors = predictions - self.y
            gradient = (self.X.T @ errors) / self.n
            self.theta = self.theta - self.alpha * gradient
            cost_history[epoch] = self.compute_cost()

        return self.theta, cost_history


class StandardScaler:
    def fit(self, X):
        self.mean_ = np.mean(X, axis=0)
        self.std_ = np.std(X, axis=0)

    def transform(self, X):
        return (X - self.mean_) / self.std_

    def fit_transform(self, X):
        self.fit(X)
        return self.transform(X)


def train_test_split(data, target, test_size, random_state):
    if random_state is not None:
        np.random.seed(random_state)

    n = data.shape[0]
    limit = int(n * test_size)

    X_train = data[:-limit]
    X_test = data[-limit:]
    y_train = target[:-limit]
    y_test = target[-limit:]
    return X_train, X_test, y_train, y_test


boston = load_boston()

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(boston.data)

alpha = 0.01
epochs = 1000

X_train, X_test, y_train, y_test = train_test_split(X_train_scaled, boston.target, test_size=0.2, random_state=42)

X_test_scaled = scaler.transform(X_test)

model = GradientDescent(X_train, y_train, alpha, epochs)
final_theta, cost_history = model.gradient_descent()

print('final_theta = ', final_theta[-1])
print('===========================================')
print('cost_history = ', cost_history[-20:])

# 绘图
plt.plot(range(epochs), cost_history)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.title('Gradient Descent Convergence')
plt.show()

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值