多层感知机MLP - helloworld
由若干个变量,推出一个结果,变量与结果之间是非线性关系。
MLPRegressor,也叫多层感知机(MLP)回归器,是一种基于神经网络的回归模型。
主要用于处理回归任务,通过学习输入特征与连续值输出之间的非线性关系,实现预测或拟合。
生产用途:
- 房价预测 :利用房屋特征(面积、位置等)训练模型,预测未来房价走势。
- 广告收益预测 :通过分析广告投放数据(如电视、广播等渠道的投入),预测广告收益。
- 天气预测 :基于气象数据训练模型,预测温度、湿度等指标。
DEMO
import numpy as np
import pandas as pd
import math
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import learning_curve
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
from joblib import dump
from joblib import load
def random_data():
"""
生成随机数,并保存到 CSV 文件中(测试数据)
:return:
"""
# 生成测试数据
np.random.seed(42)
n_samples = 1000
# 6个参数,范围[0, 10]
X = np.random.rand(n_samples, 6) * 10
# 构造非线性关系(例如:乘积+正弦函数)
y = (X[:, 0] * 0.5 + X[:, 1] ** 2 * 0.3 + np.sin(X[:, 2]) * 2 +
X[:, 3] * X[:, 4] * 0.1 + np.log(X[:, 5] + 1) * 1.5)
# 添加噪声
y += np.random.normal(0, 0.5, n_samples)
# 将数据保存到CSV文件
data = np.column_stack((X, y))
columns = ['feature1', 'feature2', 'feature3', 'feature4', 'feature5', 'feature6', 'target']
df = pd.DataFrame(data, columns=columns)
# 保存到CSV文件
csv_file = 'synthetic_data.csv'
df.to_csv(csv_file, index=False)
print(f"数据已保存到 {csv_file}")
# 数据读取函数
def load_synthetic_data(file_path):
"""
从CSV文件加载数据
参数:
file_path (str): CSV文件路径
返回:
X (np.ndarray): 特征矩阵 (n_samples, 6)
y (np.ndarray): 目标值数组 (n_samples,)
df (pd.DataFrame): 原始数据框
"""
df = pd.read_csv(file_path)
X = df[['feature1', 'feature2', 'feature3', 'feature4', 'feature5', 'feature6']].values
y = df['target'].values
return X, y, df
def train(x_train_scaled, y_train):
"""
训练模型
在 Scikit-learn 中,大多数模型不支持直接追加新数据继续训练
包括 MLPRegressor,不支持增量学习或在线学习
修改 warm_start=True,可以追加新的数据,在旧模型的基础上继续优化,但底层仍可能重新处理所有数据。
:param x_train_scaled: 训练数据集(缩放之后的数据)
:param y_train: 训练数据结果集
:return: 训练好的模型
"""
# 初始化模型
mlp = MLPRegressor(
hidden_layer_sizes=(64, 32), # 2个隐藏层,分别有64和32个神经元
activation='relu', # 激活函数('relu', 'tanh', 'logistic')
solver='adam', # 优化算法('adam', 'sgd', 'lbfgs')
max_iter=500, # 最大迭代次数
random_state=42,
early_stopping=True, # 提前停止(防止过拟合)
validation_fraction=0.1 # 验证集比例(用于early stopping)
)
# 训练模型
mlp.fit(x_train_scaled, y_train)
# 检查是否收敛(若未收敛,可增加max_iter)
# 模型实际完成的迭代次数(即优化算法真正运行的步数) - 用户预设的最大迭代次数(默认值为 200)。
print("训练是否收敛:", mlp.n_iter_ < mlp.max_iter)
return mlp
def train_grid(x_train_scaled, y_train):
"""
使用网格搜索优化超参数:
自动化调参:通过交叉验证找到最优超参数组合。
模型选择:直接获得训练好的最优模型,避免手动配置。
性能评估:通过验证集 MSE 量化模型优劣,指导后续优化方向。
:param x_train_scaled: 训练数据集(缩放之后的数据)
:param y_train: 训练数据结果集
:return: 训练好的模型
"""
param_grid = {
'hidden_layer_sizes': [(64,), (64, 32), (128, 64, 32)],
'activation': ['relu', 'tanh'],
'alpha': [0.0001, 0.001, 0.01]
}
grid_search = GridSearchCV(
MLPRegressor(max_iter=1000, random_state=42),
param_grid,
cv=3,
scoring='neg_mean_squared_error'
)
grid_search.fit(x_train_scaled, y_train)
print("最佳参数:", grid_search.best_params_)
best_mlp = grid_search.best_estimator_
# 最佳模型
return best_mlp
def print_regressor(y_test, y_pred):
"""
模型可靠性分析相关的内容
打印均方误差、拟合优度等信息
:param y_test:
:param y_pred:
:return:
"""
# 均方误差 MSE(Mean Squared Error)是预测值与真实值之差的平方的平均值:
mse = mean_squared_error(y_test, y_pred)
# 均方根误差,预测值与真实值的平均绝对偏差(开方后单位与预测值一致)。
# 是否 “误差较小” 需结合业务场景判断,例如:股票价格预测中 ±10 可能很大,而体重预测中 ±10 kg 可能正常。
rmse = math.sqrt(mse)
# 拟合优度,0-1 越大越好
r2 = r2_score(y_test, y_pred)
print(f"均方误差(MSE): {mse:.4f}")
print(f"均方根误差(RMSE): {rmse:.4f}")
print(f"R²分数: {r2:.4f}")
# 可视化预测 vs 真实值
plt.figure(figsize=(8, 6))
plt.scatter(y_test, y_pred, alpha=0.6)
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], 'r--')
plt.xlabel("True value") # 真实值
plt.ylabel("Predicted value") # 预测值
plt.title("MLPRegressor Prediction effect")
plt.savefig("mlp_regressor.png")
plt.clf()
def print_learning_curve(mlp, x_train_scaled, y_train):
"""
打印学习曲线分析
理想状态:两者接近且较高,验证 R² 随数据量增加趋于平稳。
:param mlp: 深度学习模型
:param x_train_scaled: 训练数据集(缩放之后的数据)
:param y_train: 训练数据结果集
:return:
"""
# cv=5 使用交叉验证、scoring='r2': 使用 R²(决定系数)
train_sizes, train_scores, test_scores = learning_curve(
mlp, x_train_scaled, y_train, cv=5, scoring='r2'
)
# 训练集 R² 分数的均值
plt.plot(train_sizes, np.mean(train_scores, axis=1), label="train R²")
# 验证集 R² 分数的均值
plt.plot(train_sizes, np.mean(test_scores, axis=1), label="val R²")
# 训练样本数量(Example)
plt.xlabel("Example")
# R² 分数(R² Score),范围通常在 0~1(越接近 1 越好)。
plt.ylabel("R² Score")
plt.legend()
plt.savefig("mlp_learning_curve.png")
plt.clf()
def train_mlp():
"""
训练并另存模型
:return:
"""
# 读取测试数据
x, y, df = load_synthetic_data("synthetic_data.csv")
# 随机划分训练集和测试集
x_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
# 标准化数据(神经网络对尺度敏感),将数据转为标准正态分布 N(0,1)
scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.transform(X_test)
# 训练模型
mlp = train(x_train_scaled, y_train)
# 学习曲线分析
print_learning_curve(mlp, x_test_scaled, y_test)
# 预测测试集
y_pred = mlp.predict(x_test_scaled)
# 可靠性分析
print_regressor(y_test, y_pred)
# 存储模型到文件
dump(mlp, "mlp_regressor_model.joblib")
print("模型已保存为 mlp_regressor_model.joblib")
def load_mlp():
"""
加载保存好的模型
:return:
"""
loaded_model = load("mlp_regressor_model.joblib")
return loaded_model
train_mlp()
# # 对测试集预测
# y_pred = mlp.predict(X_test_scaled) # 或 best_mlp.predict(X_test_scaled)
#
# # 对新数据预测(需相同预处理)
# new_data = [[...]] # 新样本(特征)
# new_data_scaled = scaler.transform(new_data) # 必须用训练时的scaler
# new_pred = mlp.predict(new_data_scaled)
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!
浙公网安备 33010602011771号