机器学习期末实战:从梯度下降到神经网络的核心代码与理论解析
1. 梯度下降从数学原理到代码实现梯度下降是机器学习中最基础的优化算法它的核心思想就像一个人下山的过程——沿着最陡峭的方向一步步走到谷底。我们先从一个简单的例子开始理解这个概念。假设你站在山顶眼睛被蒙住只能靠脚感受地面的倾斜程度。你会怎么做才能最快下山最自然的策略就是每次朝着坡度最陡的方向迈一步。梯度下降就是这种策略的数学表达。让我们用代码实现一个完整的线性回归梯度下降过程import numpy as np def compute_cost(x, y, w, b): 计算线性回归的代价函数 x: 特征向量 (m,) y: 目标值 (m,) w: 权重 b: 偏置 m x.shape[0] total_cost 0 for i in range(m): f_wb w * x[i] b cost (f_wb - y[i])**2 total_cost cost return total_cost / (2*m) def compute_gradient(x, y, w, b): 计算梯度 m x.shape[0] dj_dw 0 dj_db 0 for i in range(m): f_wb w * x[i] b dj_dw_i (f_wb - y[i]) * x[i] dj_db_i f_wb - y[i] dj_dw dj_dw_i dj_db dj_db_i dj_dw dj_dw / m dj_db dj_db / m return dj_dw, dj_db def gradient_descent(x, y, w_init, b_init, alpha, iters): 执行梯度下降 alpha: 学习率 iters: 迭代次数 w w_init b b_init for i in range(iters): dj_dw, dj_db compute_gradient(x, y, w, b) w w - alpha * dj_dw b b - alpha * dj_db return w, b在实际应用中学习率的选择非常关键。我曾在项目中因为学习率设置过大导致模型无法收敛就像一个人下山时步子迈得太大反而越过了最低点。一般来说可以尝试从0.01开始观察损失函数的变化曲线。2. 线性回归与逻辑回归从连续预测到分类线性回归和逻辑回归是机器学习中最基础的两种模型它们看似相似实则有着本质区别。线性回归解决的是连续值预测问题比如预测房价、预测销售额等。而逻辑回归虽然名字里有回归实际上解决的是二分类问题。让我们通过代码看看它们的区别# 线性回归预测 def linear_prediction(x, w, b): return w * x b # 逻辑回归预测 def sigmoid(z): return 1 / (1 np.exp(-z)) def logistic_prediction(x, w, b): z np.dot(x, w) b return sigmoid(z)逻辑回归的核心是sigmoid函数它把线性输出压缩到(0,1)区间可以解释为概率。我在实际项目中经常用逻辑回归做用户流失预测当概率超过0.5时我们认为用户可能会流失。两种模型的损失函数也有很大不同线性回归通常使用均方误差(MSE)逻辑回归使用交叉熵损失# 线性回归损失 def linear_loss(y_true, y_pred): return np.mean((y_true - y_pred)**2) # 逻辑回归损失 def logistic_loss(y_true, y_pred): return -np.mean(y_true * np.log(y_pred) (1-y_true)*np.log(1-y_pred))3. 神经网络基础从单层到多层感知机神经网络可以看作是多层逻辑回归的堆叠。最简单的神经网络是单层感知机而多层感知机(MLP)则加入了隐藏层大大提升了模型的表达能力。一个典型的三层神经网络结构包括输入层接收原始特征隐藏层进行特征变换输出层产生最终预测让我们实现一个简单的神经网络前向传播def initialize_parameters(n_x, n_h, n_y): 初始化神经网络参数 n_x: 输入层大小 n_h: 隐藏层大小 n_y: 输出层大小 W1 np.random.randn(n_h, n_x) * 0.01 b1 np.zeros((n_h, 1)) W2 np.random.randn(n_y, n_h) * 0.01 b2 np.zeros((n_y, 1)) return {W1: W1, b1: b1, W2: W2, b2: b2} def forward_propagation(X, parameters): 前向传播 W1 parameters[W1] b1 parameters[b1] W2 parameters[W2] b2 parameters[b2] Z1 np.dot(W1, X) b1 A1 np.tanh(Z1) # 隐藏层激活函数 Z2 np.dot(W2, A1) b2 A2 sigmoid(Z2) # 输出层激活函数 cache {Z1: Z1, A1: A1, Z2: Z2, A2: A2} return A2, cache反向传播是神经网络训练的核心它通过链式法则计算梯度。我第一次实现反向传播时花了整整三天时间调试最后发现是因为矩阵维度没对齐。这是一个常见的错误来源。4. 模型评估与调优从理论到实践训练好模型后我们需要评估它的性能。对于分类问题常用的评估指标包括准确率、精确率、召回率和F1分数。def evaluate_model(y_true, y_pred): 评估分类模型 accuracy np.mean(y_true y_pred) tp np.sum((y_true 1) (y_pred 1)) fp np.sum((y_true 0) (y_pred 1)) fn np.sum((y_true 1) (y_pred 0)) precision tp / (tp fp) if (tp fp) 0 else 0 recall tp / (tp fn) if (tp fn) 0 else 0 f1 2 * precision * recall / (precision recall) if (precision recall) 0 else 0 return {accuracy: accuracy, precision: precision, recall: recall, f1: f1}过拟合是机器学习中的常见问题。我记得在一个客户流失预测项目中模型在训练集上准确率高达98%但在测试集上只有70%这就是典型的过拟合。解决方法包括增加训练数据使用正则化(L1/L2)采用dropout技术早停(early stopping)L2正则化的实现示例def compute_cost_with_regularization(A2, Y, parameters, lambd): 带L2正则化的代价函数 lambd: 正则化系数 m Y.shape[1] cross_entropy_cost logistic_loss(Y, A2) L2_regularization_cost (lambd/(2*m)) * (np.sum(np.square(parameters[W1])) np.sum(np.square(parameters[W2]))) return cross_entropy_cost L2_regularization_cost在实际项目中我通常会先用简单的模型(如逻辑回归)建立baseline然后再尝试更复杂的模型。同时使用交叉验证来评估模型性能避免数据划分带来的偏差。