01. 机器学习基础概论

机器学习核心概念、三大范式、模型评估指标、过拟合与正则化、特征工程入门

机器学习 (Machine Learning) 是让计算机通过数据自动学习规律,无需显式编程的技术。本文从核心概念出发,建立机器学习的完整认知框架。

1. 机器学习三大范式

1.1 监督学习 (Supervised Learning)

训练数据包含 输入特征标签 (label),模型学习从输入到输出的映射关系。

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

# 特征 X 与标签 y
X = np.array([[1], [2], [3], [4], [5]])  # 房屋面积
y = np.array([100, 180, 270, 340, 430])   # 价格(万元)

# 划分训练集/测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42)

# 训练线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)

# 预测
prediction = model.predict([[6]])  # 预测 600㎡ 的价格
print(f"预测价格: {prediction[0]:.2f} 万元")

任务类型

  • 回归:输出是连续值(房价、温度)
  • 分类:输出是离散类别(邮件是否垃圾、肿瘤良恶性)

1.2 无监督学习 (Unsupervised Learning)

训练数据 只有特征,没有标签。模型自动发现数据内在结构。

from sklearn.cluster import KMeans

# 客户消费数据(无标签)
X = np.array([
    [500, 2], [600, 3], [550, 2],   # 群体 A:低频低消
    [3000, 20], [3200, 22], [2800, 18]  # 群体 B:高频高消
])

# K-Means 聚类
kmeans = KMeans(n_clusters=2, random_state=42, n_init=10)
labels = kmeans.fit_predict(X)
print(f"聚类结果: {labels}")  # [0, 0, 0, 1, 1, 1]

任务类型

  • 聚类:将数据分组(客户分群、文档聚类)
  • 降维:减少特征维度(PCA、t-SNE、可视化)
  • 关联规则:发现项集关系(购物篮分析)

1.3 强化学习 (Reinforcement Learning)

智能体 (Agent) 在环境 (Environment) 中通过 试错 学习策略,以最大化累积奖励。

当前状态 s → 选择动作 a → 环境反馈奖励 r → 转移到新状态 s'
                                            ↑_________________|

核心要素

  • 状态 (State):环境观测
  • 动作 (Action):智能体行为
  • 奖励 (Reward):环境反馈信号
  • 策略 (Policy):状态到动作的映射
  • 价值函数 (Value Function):长期累积奖励期望

2. 模型评估指标

2.1 回归指标

指标公式说明
MAE$\frac{1}{n}\sum|y_i - \hat{y}_i|$平均绝对误差,单位与目标一致
MSE$\frac{1}{n}\sum(y_i - \hat{y}_i)^2$均方误差,对异常值敏感
RMSE$\sqrt{MSE}$与目标量纲一致
$1 - \frac{SS_{res}}{SS_{tot}}$可解释方差比例,1 为完美
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

y_true = np.array([3, -0.5, 2, 7])
y_pred = np.array([2.5, 0.0, 2, 8])

print(f"MAE: {mean_absolute_error(y_true, y_pred):.3f}")
print(f"RMSE: {np.sqrt(mean_squared_error(y_true, y_pred)):.3f}")
print(f"R²: {r2_score(y_true, y_pred):.3f}")

2.2 分类指标

混淆矩阵

实际 \ 预测正类负类
正类TP (真正例)FN (假反例)
负类FP (假正例)TN (真反例)
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import classification_report, confusion_matrix

y_true = [0, 1, 0, 0, 1, 1, 0, 1]
y_pred = [0, 1, 0, 1, 1, 0, 0, 1]

print(confusion_matrix(y_true, y_pred))
# [[3 1]
#  [1 3]]

print(f"Accuracy:  {accuracy_score(y_true, y_pred):.3f}")   # (3+3)/8 = 0.75
print(f"Precision: {precision_score(y_true, y_pred):.3f}")  # 3/(3+1) = 0.75
print(f"Recall:    {recall_score(y_true, y_pred):.3f}")    # 3/(3+1) = 0.75
print(f"F1:        {f1_score(y_true, y_pred):.3f}")       # 2*0.75*0.75/(0.75+0.75) = 0.75

# 完整报告
print(classification_report(y_true, y_pred, target_names=['负类', '正类']))

不平衡数据的评估

from sklearn.metrics import roc_auc_score, average_precision_score

# AUC-ROC:不受类别分布影响,随机猜为 0.5,完美为 1.0
auc = roc_auc_score(y_true, y_proba)

# PR 曲线下的面积,更适合极度不平衡数据
ap = average_precision_score(y_true, y_proba)

2.3 交叉验证

from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold

# K 折交叉验证(分类问题用 StratifiedKFold 保证每折类别比例一致)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=cv, scoring='f1_macro')

print(f"各折得分: {scores}")
print(f"平均 F1: {scores.mean():.3f} (+/- {scores.std()*2:.3f})")

3. 过拟合与正则化

3.1 偏差-方差权衡

问题偏差 (Bias)方差 (Variance)表现解决
欠拟合训练/测试误差都高增加模型复杂度、更多特征
过拟合训练误差低,测试误差高正则化、更多数据、降维
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

# 展示过拟合:高阶多项式
degrees = [1, 3, 15]
fig, axes = plt.subplots(1, 3, figsize=(15, 4))

for ax, degree in zip(axes, degrees):
    model = make_pipeline(
        PolynomialFeatures(degree), 
        LinearRegression()
    )
    model.fit(X_train, y_train)
    
    train_score = model.score(X_train, y_train)
    test_score = model.score(X_test, y_test)
    
    ax.set_title(f"Degree {degree}\nTrain: {train_score:.3f}, Test: {test_score:.3f}")

3.2 L1/L2 正则化

类型惩罚项效果适用
L1 (Lasso)$\lambda\sum|w_i|$产生稀疏解(特征选择)高维稀疏特征
L2 (Ridge)$\lambda\sum w_i^2$权重平滑收缩多重共线性
ElasticNet$\alpha\cdot L1 + (1-\alpha)\cdot L2$兼顾两者通用场景
from sklearn.linear_model import Ridge, Lasso, ElasticNet

# L2 正则化岭回归
ridge = Ridge(alpha=1.0)  # alpha 越大约束越强
ridge.fit(X_train, y_train)

# L1 正则化 Lasso
lasso = Lasso(alpha=0.1)
lasso.fit(X_train, y_train)
print(f"非零系数数量: {np.sum(lasso.coef_ != 0)}")  # 自动特征选择

3.3 早停 (Early Stopping)

from sklearn.linear_model import SGDRegressor

model = SGDRegressor(early_stopping=True, validation_fraction=0.1,
                     n_iter_no_change=5, max_iter=1000)
model.fit(X_train, y_train)

4. 特征工程入门

4.1 数据预处理

import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder

df = pd.DataFrame({
    'age': [25, 30, None, 35],           # 数值型,有缺失
    'salary': [5000, 8000, 6000, 10000],  # 数值型
    'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou'],  # 类别型
    'level': ['junior', 'senior', 'mid', 'senior']  # 有序类别
})

# 缺失值处理
# 删除:df.dropna()
# 填充:df['age'].fillna(df['age'].median(), inplace=True)

# 标准化:均值为 0,方差为 1
scaler = StandardScaler()
df[['age', 'salary']] = scaler.fit_transform(df[['age', 'salary']])

# 归一化:缩放到 [0, 1]
normalizer = MinMaxScaler()
df[['age', 'salary']] = normalizer.fit_transform(df[['age', 'salary']])

# 类别编码:one-hot
df_encoded = pd.get_dummies(df, columns=['city'], prefix='city')

# 有序标签编码
level_map = {'junior': 0, 'mid': 1, 'senior': 2}
df['level_encoded'] = df['level'].map(level_map)

4.2 特征构造

# 时间特征
df['date'] = pd.to_datetime(['2024-01-15', '2024-06-20', '2024-12-01'])
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['dayofweek'] = df['date'].dt.dayofweek
df['is_weekend'] = df['dayofweek'].isin([5, 6]).astype(int)

# 交叉特征
df['age_salary_ratio'] = df['age'] / df['salary']

# 分箱(Binning)
df['age_group'] = pd.cut(df['age'], bins=[0, 30, 40, 100], 
                         labels=['young', 'mid', 'senior'])

# 多项式特征
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(df[['age', 'salary']])

4.3 特征选择

from sklearn.feature_selection import SelectKBest, f_classif, mutual_info_classif
from sklearn.feature_selection import RFE

# 过滤法:基于统计检验
selector = SelectKBest(score_func=f_classif, k=10)
X_selected = selector.fit_transform(X, y)

# 包装法:递归特征消除
estimator = LogisticRegression(max_iter=1000)
rfe = RFE(estimator, n_features_to_select=10)
X_rfe = rfe.fit_transform(X, y)

# 查看选中特征
selected_features = X.columns[rfe.support_]
print(f"选中特征: {selected_features.tolist()}")

5. Scikit-learn 工作流

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer

# 定义数值与类别列
numeric_features = ['age', 'salary', 'tenure']
categorical_features = ['department', 'city']

# 数值处理流水线
numeric_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())
])

# 类别处理流水线
categorical_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])

# 组合预处理
preprocess = ColumnTransformer([
    ('num', numeric_transformer, numeric_features),
    ('cat', categorical_transformer, categorical_features)
])

# 完整流水线
pipeline = Pipeline([
    ('preprocess', preprocess),
    ('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])

# 训练与评估
pipeline.fit(X_train, y_train)
print(f"测试集准确率: {pipeline.score(X_test, y_test):.3f}")

总结

机器学习工程的核心流程:

  1. 理解数据:EDA(探索性数据分析),了解分布、相关性、缺失情况
  2. 特征工程:数据清洗 → 变换 → 构造 → 选择,往往比调参更重要
  3. 模型选择与训练:从简单基线开始,逐步复杂化
  4. 评估与诊断:交叉验证 + 多维度指标,区分过拟合/欠拟合
  5. 正则化与调优:L1/L2、早停、超参数搜索
  6. 部署与监控:关注数据漂移,持续评估线上表现

“数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限。”

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ai-ml」更多文章

  1. 13. 大语言模型应用开发
  2. 12. MLOps 与实验管理
  3. 11. 模型部署与推理优化