2.线性回归实战
2.1 使用正规方程进行求解
2.1.1 简单线性回归
🚩y = w x + b 一元一次方程,在机器学习中一元表示一个特征,b 表示截距,y 表示目标值。
import numpy as np import matplotlib.pyplot as plt # 转化成矩阵 X = np.linspace(0, 10, num = 30).reshape(-1, 1) ''' np.linspace(0, 10, num = 30) 是把0~10等分为30段 为什么不实用下述代码? X = np.random.randint(0, 10, size = (30, 1)) 这是因为上面这行代码只会产生整数,而代码np.linspace(0, 10, num = 30)可以产生小数 构图更加的美观 ''' # 斜率和截距,随机生成 w = np.random.randint(1, 5, size = 1) b = np.random.randint(1, 10, size = 1) # 根据一元一次方程计算目标值y,并加上“噪声”,数据有上下波动~ y = X * w + b + np.random.randn(30, 1) plt.scatter(X, y) # 重新构造X,b截距,相当于系数w0,前面统一乘以1 X = np.concatenate([X, np.full(shape = (30, 1), fill_value = 1)], axis = 1) # 正规方程求解 θ = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y).round(2) print('一元一次方程真实的斜率和截距是:',w, b) print('通过正规方程求解的斜率和截距是:', θ) # 根据求解的斜率和截距绘制线性回归线型图 _ = plt.plot(X[:,0],X.dot(θ),color = 'green')
2.1.2 多元线性回归
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.axes3d import Axes3D # 绘制三维图像 # 转化成矩阵 x1 = np.random.randint(-150, 150, size = (300, 1)) x2 = np.random.randint(0, 300, size = (300, 1)) # 斜率和截距,随机生成 w = np.random.randint(1, 5, size = 2) b = np.random.randint(1, 10, size = 1) # 根据二元一次方程计算目标值y,并加上“噪声”,数据有上下波动~ y = x1 * w[0] + x2 * w[1] + b + np.random.randn(300, 1) fig = plt.figure(figsize = (9, 6)) ax = Axes3D(fig) ax.scatter(x1, x2, y) # 三维散点图 ax.view_init(elev = 10, azim = -20) # 调整视角 # 重新构造X,将x1、x2以及截距b,相当于系数w0,前面统一乘以1进行数据合并 X = np.concatenate([x1, x2, np.full(shape = (300, 1), fill_value = 1)], axis = 1) w = np.concatenate([w, b]) # 正规方程求解 θ = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y).round(2) print('二元一次方程真实的斜率和截距是:', w) print('通过正规方程求解的斜率和截距是:', θ.reshape(-1)) # # 根据求解的斜率和截距绘制线性回归线型图 x = np.linspace(-150, 150, 100) y = np.linspace(0, 300, 100) z = x * θ[0] + y * θ[1] + θ[2] _ = ax.plot(x,y,z ,color = 'red')
2.2 机器学习库scikit−learn
🚩这个库我们其实在 线性回归的基本概念以及正规方程 就已经有了介绍,下面的两个代码也是调用函数改写上述的两个代码。
scikit-learn官网
2.2.1scikit−learn实现简单线性回归
from sklearn.linear_model import LinearRegression import numpy as np import matplotlib.pyplot as plt # 转化成矩阵 X = np.linspace(0, 10, num = 30).reshape(-1, 1) # 斜率和截距,随机生成 w = np.random.randint(1, 5, size = 1) b = np.random.randint(1, 10, size = 1) # 根据一元一次方程计算目标值y,并加上“噪声”,数据有上下波动~ y = X * w + b + np.random.randn(30, 1) plt.scatter(X, y) # 使用scikit-learn中的线性回归求解 model = LinearRegression() model.fit(X, y) w_ = model.coef_ b_ = model.intercept_ print('一元一次方程真实的斜率和截距是:',w, b) print('通过scikit-learn求解的斜率和截距是:',w_, b_) _ = plt.plot(X, X.dot(w_) + b_, color = 'green')
2.2.2 scikit−learn实现多元线性回归
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.axes3d import Axes3D # 转化成矩阵 x1 = np.random.randint(-150, 150,size = (300, 1)) x2 = np.random.randint(0, 300,size = (300, 1)) # 斜率和截距,随机生成 w = np.random.randint(1, 5, size = 2) b = np.random.randint(1, 10, size = 1) # 根据二元一次方程计算目标值y,并加上“噪声”,数据有上下波动~ y = x1 * w[0] + x2 * w[1] + b + np.random.randn(300, 1) fig = plt.figure(figsize = (9, 6)) ax = Axes3D(fig) ax.scatter(x1, x2, y) # 三维散点图 ax.view_init(elev = 10, azim = -20) # 调整视角 # 重新构造X,将x1、x2以及截距b,相当于系数w0,前面统一乘以1进行数据合并 X = np.concatenate([x1, x2], axis = 1) # 使用scikit-learn中的线性回归求解 model = LinearRegression() model.fit(X, y) w_ = model.coef_.reshape(-1) b_ = model.intercept_ print('二元一次方程真实的斜率和截距是:', w, b) print('通过scikit-learn求解的斜率和截距是:', w_, b_) # # 根据求解的斜率和截距绘制线性回归线型图 x = np.linspace(-150, 150, 100) y = np.linspace(0, 300, 100) z = x * w_[0] + y * w_[1] + b_ _ = ax.plot(x, y, z ,color = 'green')
2.3 线性回归预测房价
2.3.1 数据加载
首先导包:
import numpy as np from sklearn import datasets from sklearn.linear_model import LinearRegression
我们要实现的是对 波士顿 这个国家进行房价预测,有关 波士顿 的数据,可以直接用代码:
boston = datasets.load_boston()
我们来看一下 datasets.load_boston()
里面都有哪些数据:
数据由三部分组成:
我们把这些信息分开来处理:
boston = datasets.load_boston() X = boston['data'] # 数据,这些数据影响了房价,统计指标 y = boston['target'] # 房价,24就表示24万美金 # CRIM:犯罪率 # NOX:空气污染,N含量 # TAX:税收 # 这些指标都和放假有关 feature_names = boston['feature_names'] # 具体指标
2.3.2 数据查看
# 506 表示 506 个统计样本 # 13 表示影响房价的 13 个属性 X.shape
# 506 个房子 # X -----> y 是一一对应的 # 数据 -----> 目标值对应 y.shape
2.3.3 数据拆分
# 506个数据、样本 # 拆分成两份:一份 80%用于训练,一份20%用于验证 # 拿出其中的80%,交给算法(线性回归),去进行学习、总结、拟合函数 # 20%作用:验证,测一测,看看算法,学习80%结束,是否准确 # 如何划分:利用 numpy 的 shuffle 打乱数据 index = np.arange(506) np.random.shuffle(index) index
506×80%≈405,故我们拿出打乱后的前 405 个数据用于训练算法,其余数据用于验证算法:
# 80% 训练数据 train_index = index[:405] X_train = X[train_index] y_train = y[train_index] # 20% 测试数据 test_index = index[405:] X_test = X[test_index] y_test = y[test_index]
2.3.4 数据建模
np.set_printoptions(suppress = True) # 不使用科学计数法 model = LinearRegression(fit_intercept = True) # 建模:算法、方程 model.fit(X_train, y_train) # 建模获取了斜率,斜率有大有小,有正有负 # 斜率为正代表正相关(面积),为负代表负相关(犯罪率) display(model.coef_, model.intercept_)
2.3.5 模型验证
# 模型预测的结果:y_ y_ = model.predict(X_test).round(2) # 展示前 30 个: display(y_[:30]) # 展示真实结果的前 30 个: display(y_test[:30])
算法的预测难免会有异常值,这是 不可避免的!
2.3.6 模型评估
# 最大值是 1,最小值可以小于 0 # 这个指标越接近 1,说明算法越优秀 model.score(X_test, y_test)
# 再来判断一下训练数据的得分 model.score(X_train, y_train)
显然,训练数据的得分是高的,这就好比我们在考试前都会做模拟题,我们如果考试卷的大部分题目都和模拟题是一样的,那么我们的分数就会高一些,如果考试的题目都是新题,那么我们的分数就会低一些
当然,我们评测数据不止这一个方法,下面简单介绍一下别的方法:
# 最小二乘法 from sklearn.metrics import mean_squared_error # 这个是测试数据,对应的是 20% y_pred = model.predict(X_test) y_true = y_test mean_squared_error(y_true, y_pred)
我们再来看那 80 % 的训练数据:
# 80% 的训练数据: mean_squared_error(y_train, model.predict(X_train))
注意我们这里的分数是error,即 越小越好!