【机器学习】机器学习回归模型全解析:线性回归、多项式回归、过拟合与泛化、向量相关性与岭回归的理论与实践
🥦机器学习中的回归任务及其实现
·
机器学习中的回归任务是指通过训练数据学习一个映射关系,来预测连续值输出。与分类任务不同,回归任务的输出是一个实数值。
回归任务的应用场景
- 房价预测:根据位置、面积、房间数等特征预测房价。
- 股市预测:根据历史数据预测股票价格。
- 气象预测:根据天气数据预测温度、湿度等数值。
回归评价指标
常用的回归模型评价指标包括:
- ***均方误差(MSE)***:衡量模型预测值与真实值之间的平均误差的平方。
- ***平均绝对误差(MAE)***:衡量模型预测值与真实值之间的平均绝对误差。
- ***R²(决定系数)***:表示模型拟合数据的好坏,值越接近1表示拟合越好。
🥦线性回归模型
线性回归是最基本的回归方法之一,其假设目标值与输入特征之间存在线性关系。
线性回归模型公式
代码示例:使用Python的scikit-learn实现线性回归
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
# 创建示例数据
X = np.array([[1], [2], [3], [4], [5]]) # 特征
y = np.array([1, 2, 3, 4, 5]) # 目标值
# 创建线性回归模型
model = LinearRegression()
# 拟合数据
model.fit(X, y)
# 打印回归系数
print("回归系数:", model.coef_)
print("截距:", model.intercept_)
# 预测
y_pred = model.predict(X)
# 绘制结果
plt.scatter(X, y, color='blue') # 原数据
plt.plot(X, y_pred, color='red') # 拟合线
plt.show()
运行结果如下:
🥦机器学习中的最优化方法
- 梯度下降(Gradient Descent):通过计算损失函数相对于参数的梯度,并更新参数,逐步逼近最优解。
- 最小二乘法(Least Squares):用于线性回归模型,找到使得所有样本点的误差平方和最小的参数。
代码示例:使用梯度下降优化线性回归
import numpy as np
# 创建数据
X = np.array([1, 2, 3, 4, 5])
y = np.array([1, 2, 3, 4, 5])
# 初始化参数
w = 0.0
b = 0.0
learning_rate = 0.01
epochs = 1000
# 梯度下降
for epoch in range(epochs):
# 计算预测值
y_pred = w * X + b
# 计算损失函数的梯度
dw = -2 * np.sum(X * (y - y_pred)) / len(X)
db = -2 * np.sum(y - y_pred) / len(X)
# 更新参数
w -= learning_rate * dw
b -= learning_rate * db
if epoch % 100 == 0:
print(f"Epoch {epoch}: w = {w}, b = {b}")
print(f"训练完毕: w = {w}, b = {b}")
运行结果如下:
🥦多项式回归
多项式回归是通过引入高阶项来捕捉特征之间的非线性关系。
代码示例:使用scikit-learn实现多项式回归
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
# 创建数据
X = np.array([1, 2, 3, 4, 5]).reshape(-1, 1)
y = np.array([1, 4, 9, 16, 25])
# 创建多项式特征
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
# 拟合多项式回归模型
model = LinearRegression()
model.fit(X_poly, y)
# 预测
y_pred = model.predict(X_poly)
# 绘制结果
plt.scatter(X, y, color='blue') # 原数据
plt.plot(X, y_pred, color='red') # 拟合曲线
plt.show()
运行结果如下:
🥦过拟合与泛化
- 过拟合:当模型在训练数据上表现很好,但在新数据上表现差时,说明模型过拟合了训练数据。为了避免过拟合,可以使用正则化技术。
- 泛化:模型能够适应新数据,且不仅仅是训练数据。
代码示例:通过增加多项式的阶数来观察过拟合
# 增加多项式阶数,观察是否发生过拟合
poly = PolynomialFeatures(degree=10)
X_poly = poly.fit_transform(X)
model.fit(X_poly, y)
y_pred = model.predict(X_poly)
plt.scatter(X, y, color='blue')
plt.plot(X, y_pred, color='red')
plt.show()
🥦向量相关性与岭回归
岭回归(Ridge Regression)是线性回归的一种正则化形式,旨在防止过拟合。
岭回归模型
岭回归通过在损失函数中加入 L2 正则化项来减少模型的复杂度:
其中, 是正则化参数。
代码(岭回归实现)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
# 假设数据 X 和 y 已经加载到变量中
X = np.random.rand(100, 1) # 生成100个随机特征数据
y = 2 * X + np.random.randn(100, 1) # 生成目标变量
# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建岭回归模型
ridge_model = Ridge(alpha=1.0)
# 训练模型
ridge_model.fit(X_train, y_train)
# 预测
y_ridge_pred = ridge_model.predict(X_test)
# 计算MSE和R²
mse_ridge = mean_squared_error(y_test, y_ridge_pred)
r2_ridge = r2_score(y_test, y_ridge_pred)
# 打印结果
print(f"岭回归 - MSE: {mse_ridge:.2f}, R²: {r2_ridge:.2f}")
# 可视化结果
plt.scatter(X_test, y_test, color='blue', label='实际值')
plt.plot(X_test, y_ridge_pred, color='purple', label='岭回归预测值')
plt.xlabel('特征值')
plt.ylabel('目标值')
plt.legend()
plt.show()
运行结果如下:
岭回归 - MSE: 1.90, R²: -0.05
-
MSE(均方误差): 1.90
MSE 是衡量模型预测与实际值之间差异的一个指标,表示的是预测值与真实值之间误差的平方的平均值。较小的 MSE 值通常意味着模型的预测误差较小。这里的 1.90 表示模型的预测误差相对较大,说明模型对测试集的预测并不准确。 -
R²(决定系数): -0.05
R² 是用于评估回归模型拟合度的一个指标,表示模型对数据的解释能力。R² 的范围通常是 [0, 1],越接近 1 表示模型的解释能力越强;值为 0 时表示模型不能解释数据中的变异;而负值通常意味着模型的表现非常差,甚至比一个简单的平均值模型还要差。
负值:当 R² 为负时,通常意味着模型非常不合适,预测的效果比一个简单的基准模型(比如直接预测所有输出为目标变量的平均值)还要差。
在这种情况下,R² = -0.05 意味着岭回归模型的预测效果非常差,模型不仅没有提供有用的信息,而且其预测结果远不如基准模型。
毕竟这是虚假的数据,文章的最后我会使用真实的数据集进行测试
解释:
正则化参数:alpha 控制正则化的强度,增大 alpha 会使模型更加简单,从而避免过拟合。
🥦局部回归
局部回归(Local Regression)是指针对每一个查询点,利用其附近的点来进行回归。常见的方法是 LOESS 或 LOWESS(局部加权回归)。
代码(局部回归实现)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
# 假设数据 X 和 y 已经加载到变量中
# 示例:X = np.random.rand(100, 1) # 生成100个随机特征数据
# y = 2 * X + np.random.randn(100, 1) # 生成目标变量
# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建KNN回归模型
knn_model = KNeighborsRegressor(n_neighbors=5)
# 训练模型
knn_model.fit(X_train, y_train)
# 预测
y_knn_pred = knn_model.predict(X_test)
# 计算MSE和R²
mse_knn = mean_squared_error(y_test, y_knn_pred)
r2_knn = r2_score(y_test, y_knn_pred)
# 打印结果
print(f"KNN回归 - MSE: {mse_knn:.2f}, R²: {r2_knn:.2f}")
# 可视化结果
plt.scatter(X_test, y_test, color='blue', label='实际值')
plt.plot(X_test, y_knn_pred, color='orange', label='KNN回归预测值', linewidth=2)
plt.xlabel('特征值')
plt.ylabel('目标值')
plt.legend()
plt.show()
🥦代码实践(CoNLL-2003数据集)
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
from sklearn.neighbors import KNeighborsRegressor
from gensim.models import Word2Vec
# 1. 加载数据并解析
def load_data(file_path):
sentences = []
sentence = []
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
if line.strip(): # 非空行
word = line.split()[0] # 提取词
sentence.append(word)
else:
if sentence:
sentences.append(sentence)
sentence = []
if sentence: # 添加最后一个句子
sentences.append(sentence)
return sentences
# 加载训练、验证和测试集
train_sentences = load_data("./data/coll2003/train.txt")
valid_sentences = load_data("./data/coll2003/valid.txt")
test_sentences = load_data("./data/coll2003/test.txt")
# 2. 训练Word2Vec模型并将句子转换为向量
embedding_dim = 100 # 嵌入维度,可以根据需要调整
w2v_model = Word2Vec(sentences=train_sentences, vector_size=embedding_dim, window=5, min_count=1, workers=4)
def sentence_to_vector(sentence, model, embedding_dim):
# 过滤出句子中存在于词向量模型中的词
vectors = [model.wv[word] for word in sentence if word in model.wv]
if len(vectors) > 0:
# 计算词向量的均值
vector = np.mean(vectors, axis=0)
else:
# 如果句子中没有任何词在词汇表中,返回一个零向量
vector = np.zeros(embedding_dim)
return vector
# 应用改进的函数
X_train = np.array([sentence_to_vector(sentence, w2v_model, embedding_dim) for sentence in train_sentences])
X_valid = np.array([sentence_to_vector(sentence, w2v_model, embedding_dim) for sentence in valid_sentences])
X_test = np.array([sentence_to_vector(sentence, w2v_model, embedding_dim) for sentence in test_sentences])
# 检查形状
print("X_train shape:", X_train.shape)
print("X_valid shape:", X_valid.shape)
print("X_test shape:", X_test.shape)
# 假设我们有目标值 y(例如,每个句子的标签或分数),这里使用随机数据进行演示
y_train = np.random.rand(len(X_train)) # 替换为实际的目标值
y_valid = np.random.rand(len(X_valid)) # 替换为实际的目标值
y_test = np.random.rand(len(X_test)) # 替换为实际的目标值
# 3. 线性回归
linear_model = LinearRegression()
linear_model.fit(X_train, y_train)
y_pred_train = linear_model.predict(X_train)
y_pred_valid = linear_model.predict(X_valid)
y_pred_test = linear_model.predict(X_test)
print("线性回归训练集MSE:", mean_squared_error(y_train, y_pred_train))
print("线性回归验证集MSE:", mean_squared_error(y_valid, y_pred_valid))
print("线性回归测试集MSE:", mean_squared_error(y_test, y_pred_test))
# 4. 多项式回归
degree = 2 # 多项式的阶数,可以调整
poly_features = PolynomialFeatures(degree=degree)
X_train_poly = poly_features.fit_transform(X_train)
X_valid_poly = poly_features.transform(X_valid)
X_test_poly = poly_features.transform(X_test)
poly_model = LinearRegression()
poly_model.fit(X_train_poly, y_train)
y_pred_train_poly = poly_model.predict(X_train_poly)
y_pred_valid_poly = poly_model.predict(X_valid_poly)
y_pred_test_poly = poly_model.predict(X_test_poly)
print("多项式回归训练集MSE:", mean_squared_error(y_train, y_pred_train_poly))
print("多项式回归验证集MSE:", mean_squared_error(y_valid, y_pred_valid_poly))
print("多项式回归测试集MSE:", mean_squared_error(y_test, y_pred_test_poly))
# 5. 岭回归
alpha = 1.0 # 正则化强度,可以调整
ridge_model = Ridge(alpha=alpha)
ridge_model.fit(X_train, y_train)
y_pred_train_ridge = ridge_model.predict(X_train)
y_pred_valid_ridge = ridge_model.predict(X_valid)
y_pred_test_ridge = ridge_model.predict(X_test)
print("岭回归训练集MSE:", mean_squared_error(y_train, y_pred_train_ridge))
print("岭回归验证集MSE:", mean_squared_error(y_valid, y_pred_valid_ridge))
print("岭回归测试集MSE:", mean_squared_error(y_test, y_pred_test_ridge))
# 6. 局部回归(KNN回归)
n_neighbors = 10 # 邻居数,可以调整
knn_model = KNeighborsRegressor(n_neighbors=n_neighbors)
knn_model.fit(X_train, y_train)
y_pred_train_knn = knn_model.predict(X_train)
y_pred_valid_knn = knn_model.predict(X_valid)
y_pred_test_knn = knn_model.predict(X_test)
print("局部回归(KNN)训练集MSE:", mean_squared_error(y_train, y_pred_train_knn))
print("局部回归(KNN)验证集MSE:", mean_squared_error(y_valid, y_pred_valid_knn))
print("局部回归(KNN)测试集MSE:", mean_squared_error(y_test, y_pred_test_knn))
# 7. 总结结果
results = {
"线性回归测试集MSE": mean_squared_error(y_test, y_pred_test),
"多项式回归测试集MSE": mean_squared_error(y_test, y_pred_test_poly),
"岭回归测试集MSE": mean_squared_error(y_test, y_pred_test_ridge),
"局部回归(KNN)测试集MSE": mean_squared_error(y_test, y_pred_test_knn),
}
print("\n测试集误差比较:")
for model, mse in results.items():
print(f"{model}: {mse}")
运行结果如下:
表格如下:
🥦指标评估详解
线性回归:
- 在训练集、验证集和测试集上的MSE都在0.08左右,说明模型在三个数据集上的误差比较一致,且误差较小。这意味着线性回归模型在这组数据上的拟合情况比较稳定,适度的表现出良好的泛化性。
多项式回归:
- 训练集MSE较小(0.06),但验证集和测试集上的MSE相对较大(验证集为0.24,测试集为0.33)。
这种差异表明多项式回归可能出现了过拟合问题。在训练集上表现很好,但在验证集和测试集上表现较差,无法很好地泛化。这可能是因为多项式模型的复杂度较高,容易捕捉到训练数据的噪声。
岭回归:
- 在训练集、验证集和测试集上的MSE都在0.08左右,与线性回归的表现相似。
由于岭回归使用了正则化技术,有助于减少模型的过拟合问题。因此,岭回归在三个数据集上的误差较为一致,说明它的泛化能力较好。
局部回归(KNN):
- 训练集上的MSE为0.07,而验证集和测试集上的MSE略高,为0.09。
KNN的表现也较为稳定,但比线性回归和岭回归的误差稍高。这可能是因为局部回归的特性更依赖于邻近数据点,泛化能力相对有限,尤其是在样本较大的测试集上。
总结
线性回归和岭回归在这组数据上表现良好,MSE较低且较为稳定,适合在简单数据特征和较少噪声的场景下使用。
多项式回归出现过拟合,适用于更复杂的特征关系或在特征数量增加、正则化改进的情况下才可能取得更好的泛化效果。
局部回归(KNN)适合小数据集或对局部关系要求更高的任务,但在大数据集或需要全局建模的任务中表现略逊色。
🥦总结
本文深入探讨了机器学习中的回归任务,并通过多种回归模型的详细介绍,帮助大家理解如何利用回归方法解决现实中的预测问题。通过对线性回归、多项式回归、岭回归、局部回归等模型的剖析,我们掌握了不同场景下回归任务的最佳选择和优化技巧。
关键点回顾:
- 回归任务的基本概念:回归任务旨在预测一个连续的输出值,广泛应用于房价预测、股市预测等领域。
- 线性回归模型:简单且高效,通过最小化均方误差来训练模型,适合处理线性关系数据。
- 多项式回归:扩展了线性回归,通过加入高次项处理非线性问题,适用于较复杂的数据关系。
- 过拟合与泛化问题:过拟合是回归模型常见的难题,通过正则化(如岭回归)或减少模型复杂度来提高模型的泛化能力。
- 岭回归与正则化:通过在损失函数中加入L2正则化项,控制模型复杂度,防止过拟合,适用于高维数据或特征相关性强的数据。
- 局部回归(KNN回归):针对每个数据点,使用其邻近的数据点进行回归,适用于数据呈现局部模式的情况。
每种回归方法都有其适用的场景和优缺点,在实际应用中,我们需要根据具体问题选择合适的模型。此外,我们还探讨了梯度下降法和最优化方法,它们是回归模型训练中的核心步骤。为了提升模型性能,我们需要时刻关注模型的泛化能力,避免过拟合带来的负面影响。
挑战与创造都是很痛苦的,但是很充实。
- 点赞
- 收藏
- 关注作者
评论(0)