ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

深度学习回归实战:从手写梯度下降到Keras与时间序列预测

深度学习回归实战:从手写梯度下降到Keras与时间序列预测 简介这是一套面向初学者的Python深度学习实战资源聚焦回归与分类任务涵盖全连接神经网络、Logistic回归、随机梯度下降、Keras建模以及LSTM/RNN等时序模型适合想通过具体代码理解神经网络训练与评估流程的开发者。压缩包共26个文件包括12个Python脚本、6个Jupyter Notebook、6个CSV数据集、1个说明文档和1个工程配置文件整体约1006KB虽然体积不大但代码与样例数据齐全便于直接运行和对照学习。当前已有277人学习下载。资源中提供了可交互的Notebook分步演示和可复用脚本覆盖数据预处理、模型构建、超参数调整、早停与验证等关键环节并结合美元兑印度卢比预测、气候变化预测、购买行为预测、MNIST分类等真实场景帮助读者快速掌握Python深度学习的工程实现思路为后续研究更复杂模型打下基础。1. 拿到代码先别跑从手写 SGD 到 Keras这份资源到底想让你练什么一个名叫 Deep-Learning-in-Python-master 的压缩包里面既有Gradient_Descent.py这种徒手实现梯度下降的脚本又有Regresison_Using_Keras_NN.py这类直接用 Keras 搭神经网络的完整代码还夹着Time Series Prediction.ipynb和ClimateChange_Prediction.ipynb两个时间序列回归案例。乍看像是大杂烩其实它把深度学习回归的训练路径拆成了三个阶段先理解优化器的底层原理再上手全连接网络最后处理序列建模。对刚接触回归任务的 Python 开发者来说这套组合比单独看框架文档更有价值因为每个 notebook 里都留着可以对比的模型版本比如model1_vs_model2_vs_model3.py就是典型的实验管理思路。2. 梯度下降与回归损失先把 MSE 和优化器原理吃透回归任务和分类任务最本质的区别在输出层分类用 softmax 输出概率回归用线性神经元输出连续值。判断回归模型好坏最常用的损失函数是均方误差MSE也就是预测值与真实值差的平方的平均。某些场景下也会用平均绝对误差MAE它对异常值更鲁棒但梯度在零点不连续训练初期容易抖动。这份代码包里的Mean_Squared_Error.py正好演示了如何从零手写这个损失值得先读一遍。2.1 手写梯度下降看懂迭代才是关键Keras、PyTorch 都封装了优化器但如果你不清楚参数是怎么更新的后面调学习率就像盲人摸象。最常见的随机梯度下降SGD更新规则是theta theta - learning_rate * gradient这里的gradient是损失函数对每个参数的偏导。下面是这份资源里Gradient_Descent.py对应的核心逻辑我用 numpy 复刻了一下import numpy as np # 生成线性回归数据: y 3x 2 noise np.random.seed(0) X np.random.rand(100, 1) * 10 y 3 * X 2 np.random.randn(100, 1) * 2 # 初始化权重和偏置 w np.random.randn(1) b 0.0 learning_rate 0.01 epochs 200 for epoch in range(epochs): # 前向计算: 预测值 y_pred X * w b # 均方误差损失 loss np.mean((y_pred - y) ** 2) # 计算梯度 (推导自 d(loss)/dw 和 d(loss)/db) grad_w np.mean(2 * (y_pred - y) * X) grad_b np.mean(2 * (y_pred - y)) # 更新参数 w - learning_rate * grad_w b - learning_rate * grad_b if epoch % 20 0: print(fepoch {epoch}: loss{loss:.4f}, w{w[0]:.4f}, b{b:.4f})这段代码里grad_w和grad_b是手动推导的梯度没有用任何自动求导库。注意np.mean而不是np.sum因为 MSE 本身就是对每个样本误差取平均这样损失值不受 batch size 影响。学习率learning_rate是 0.01如果设得太大比如 1.0loss 会震荡甚至爆掉设得太小比如 0.0001收敛极慢。这份代码里没有加入 momentum你可以在SGD_ADAM_MNIST.py里看到 Adam 和 SGD 的对比——Adam 因为自适应调整每个参数的学习率往往在初始阶段收敛更快。2.2 学习率策略什么时候调低什么时候用动量一份好的回归代码不该只调一个学习率跑到底。下表总结了这份代码包里涉及的学习率策略策略实现方式适用场景常见陷阱固定学习率optimizer SGD(learning_rate0.01)简单线性模型复杂网络容易陷入局部最优指数衰减ReduceLROnPlateau或指数调度训练中后期需要精细收敛衰减太快导致欠拟合动量SGD(learning_rate0.01, momentum0.9)深层全连接、卷积动量过大会越过最优解AdamAdam(learning_rate0.001)大多数回归任务对学习率敏感建议保持默认在Stochastic_Gradient_Descent_With_LearningRates.py中你会发现一个值得记住的现象全批量梯度下降batch size 全部样本更新稳定但计算量大随机梯度下降每次一个样本收敛路径嘈杂但能逃离局部极小值小批量 SGD 是两者的折中。回归任务里我一般优先用小批量 SGD momentum效果比纯 Adam 更容易排查问题因为 Adam 的自适应机制会掩盖一些特征缩放不当的问题。3. 用 Keras 搭回归网络预处理、全连接层和训练流程当你理解了梯度下降和损失函数下一步就是把网络搭建交给框架。Keras 的优势在于它的SequentialAPI 可以让你像搭积木一样逐层定义模型调试起来非常直观。Regresison_Using_Keras_NN.py这个文件展示了典型的回归网络结构输入层 → 若干隐藏层 → 线性输出层。但代码之前数据的形状和分布往往决定了模型能不能收敛。3.1 回归任务的标准化没有归一化网络很难训练如果特征的单位差异很大比如房价预测中面积是几十到几百房龄是几年到几十年特征值范围不同会导致梯度方向被大数值特征主导。常见做法是对每个特征做 Z-score 标准化让均值为 0方差为 1。下面是使用 Scikit-learn 和 Keras 的标准流程import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.optimizers import Adam # 假设加载了 CSV 数据, 例如 cps.csv df pd.read_csv(cps.csv) X df.drop(columns[salary]).values # 特征 y df[salary].values.reshape(-1, 1) # 目标 # 归一化特征和目标 (回归目标通常也归一化) scaler_X StandardScaler() scaler_y StandardScaler() X_scaled scaler_X.fit_transform(X) y_scaled scaler_y.fit_transform(y) # 切分训练/验证集 X_train, X_val, y_train, y_val train_test_split( X_scaled, y_scaled, test_size0.2, random_state42) # 构建全连接回归网络 model Sequential([ Dense(64, activationrelu, input_shape(X_train.shape[1],)), Dense(32, activationrelu), Dense(1, activationlinear) # 回归输出层不使用 sigmoid/softmax ]) model.compile(optimizerAdam(learning_rate0.001), lossmse, metrics[mae])StandardScaler拟合只能用训练集不能把测试集或验证集混进去否则信息泄露会导致验证评估过于乐观。输出层用了linear激活函数这是回归和分类最关键的代码区别——如果这里错误地用了relu或sigmoid模型将无法输出负值或任意范围的连续值。metrics[mae]是方便观察平均绝对误差它和 MSE 的单位一致解释起来更直观。3.2 训练过程batch size 和 epochs 的影响数据准备好后调用model.fit开始训练。但回归任务里epochs和batch_size直接影响最终精度和训练时间。下面是这段代码的继续history model.fit( X_train, y_train, validation_data(X_val, y_val), epochs200, batch_size32, verbose1 ) # 预测时注意要还原到原始尺度 y_pred_scaled model.predict(X_val) y_pred scaler_y.inverse_transform(y_pred_scaled)batch_size32是最常用的默认值它平衡了梯度稳定性和计算效率。如果batch_size设为整个训练集大小每轮更新次数太少设为 1噪声过大且 GPU 利用率低。validation_data参数让 Keras 在每轮结束后自动评测验证集损失这是监控过拟合最简单的手段。训练完成后inverse_transform非常容易被忽略——你训练时把目标归一化了预测出的也是归一化值不还原成原始单位业务方看不懂结果。4. 早停、验证集与模型对比把过拟合压下去的参数化实践有了基础网络下一步就该谈优化和选型了。代码包里的optimization_earlystopping_validation.py和model1_vs_model2_vs_model3.py是递进关系前者教你如何自动寻找合适的训练轮数后者教你把不同结构的模型放在同一套数据上比较。这两步是深度学习回归实验的标配——不是跑一个模型就算完而是要有对比、有证据地选定最终方案。4.1 用早停法保护模型看验证集而非训练集训练轮数太少欠拟合太多又过拟合。手动盯着验证损失调很累Keras 提供了EarlyStopping回调它会在验证损失连续多个 epoch 没有改善时自动停止训练并通过restore_best_weights把参数恢复到验证集表现最好的位置。from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint early_stop EarlyStopping( monitorval_loss, patience20, restore_best_weightsTrue ) checkpoint ModelCheckpoint( best_model.h5, monitorval_loss, save_best_onlyTrue ) history model.fit( X_train, y_train, validation_data(X_val, y_val), epochs500, batch_size32, callbacks[early_stop, checkpoint], verbose0 )patience20的含义是验证损失连续 20 个 epoch 没有变好就停止。这个值设置太大会浪费计算资源太小会在损失曲线暂时平坦时过早停止。经验上小数据集可以从patience10开始大数据集可以放宽到50。ModelCheckpoint配合save_best_onlyTrue让你只保留最优模型文件避免磁盘被中间版本占满。这里我特别想强调早停的监控指标必须是验证集损失而不是训练损失。因为训练损失几乎一定是递减的它不能反映泛化能力。4.2 模型对比实验控制变量才能下结论资源里的model1_vs_model2_vs_model3.py实际上就是一个简单的超参数搜索。你可以在代码里定义多个网络结构比如model1为单隐层model2为两个隐层model3为带 dropout 的深层网络。为了公平比较每个模型使用相同的数据切分、相同的优化器和相同的 metrics唯一改变的是网络结构本身。这才是「对比实验」的底线。模型配置隐层神经元数dropout验证 MAE验证损失model132无12.4186.3model264 32无8.996.7model364 320.29.5102.1上面是典型结果。多一层网络明显提升了拟合能力但加了 dropout 后验证 MAE 反而略高——这说明当前数据规模下过拟合并不严重dropout 带来的是信息损失。判断依据是训练集和验证集损失之间的差距如果训练损失远低于验证损失就是过拟合信号如果两者都很高则是欠拟合应先调大模型容量。你可以在model1_vs_model2_plotting.py里看到绘制训练曲线的方式对比两条 loss 曲线比只看最终数字可靠得多。5. 时间序列回归LSTM 和全连接网络在序列数据上的分工Time Series Prediction.ipynb和ClimateChange_Prediction.ipynb是本资源里最有意思的部分因为它们把回归从静态特征扩展到了时间序列。预测下个月的气温、下一季度的汇率输入不再是独立样本而是一个滑动窗口。如果直接把时间点作为特征喂给全连接网络模型学不到序列内部的先后依赖关系。这时候就需要轮换神经网络RNN或者更常说的 LSTM来记住窗口内的时间模式。5.1 构造滑动窗口样本把时间序列变成监督学习用 LSTM 之前必须把原始时间序列转换成「过去 N 个时间步 → 预测下一个时间步」的样本形状。Keras 的 LSTM 层期望输入形状为(samples, timesteps, features)下面是典型构造import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 假设 data 是一维气候温度序列 data np.array([20.1, 20.8, 21.5, 22.0, 22.7, 23.4]) def create_sequences(data, window_size): X, y [], [] for i in range(len(data) - window_size): X.append(data[i:iwindow_size]) y.append(data[iwindow_size]) return np.array(X), np.array(y) WINDOW 3 X, y create_sequences(data, WINDOW) X X.reshape(-1, WINDOW, 1) # 单特征 model Sequential([ LSTM(16, activationrelu, input_shape(WINDOW, 1)), Dense(8, activationrelu), Dense(1) # 回归输出 ]) model.compile(optimizeradam, lossmse, metrics[mae])create_sequences中window_size3表示用前 3 天的数据预测第 4 天。input_shape的第一个维度是时间步数第二个是特征维度。如果你有两个特征比如温度和湿度那么最后一段X的形状应该是(样本数, WINDOW, 2)LSTM 会自动处理多特征输入。这里有个容易踩的坑activationrelu在 LSTM 里并不总是首选实践中tanh或默认的tanh在回归任务上更稳定你可以试一下替换后验证损失的差异。5.2 和随机森林回归、岭回归等传统模型的实际对比时间序列预测不一定非得用深度学习。机场流量预测、电力负荷曲线这类有明显周期性的序列用随机森林回归模型配合滞后特征lag features也常能拿到不错的结果。但 LSTM 的优势在于它能自动学习长期依赖而随机森林只能从给定的滞后特征里做非线性组合。实际操作中我建议先用传统模型建立一个基线把前 7 天的值作为特征用随机森林回归或岭回归预测第 8 天。如果这个基线的验证 MAE 已经足够满足业务要求那就没必要上 LSTM因为深度学习模型需要更多数据、更长训练时间和更复杂的调参。反之如果传统模型在验证集上明显欠拟合再切换到 LSTM 结构会更有说服力。这份代码包里README.md虽然没有写明这个对比步骤但model1_vs_model2_vs_model3.py的实验思路完全可以迁移到时间序列任务里为传统模型、全连接网络、LSTM 各跑一遍记录验证损失然后看哪个模型在独立测试集上表现最稳。最后有一个值得养成的习惯验证预测结果时不要把多个时间步的预测值直接拼在一起计算整体误差。因为 LSTM 用滚动预测时前一步的误差会累积到下一步输入中导致误差被放大。正确做法是像ClimateChange_Prediction.ipynb里可能展示的那样先预测一步用真实值作为下一步输入再计算逐点误差——这才能真实反映模型在每一步的稳态表现。本文还有配套的精品资源点击获取
返回列表