☰
6个经典机器学习实战项目解析:从回归到自监督学习
2026/11/4 9:10:46 网站建设 项目流程

1. 机器学习经典实战项目解析

作为一名从业多年的机器学习工程师,我深知实战项目对于掌握核心技能的重要性。今天我将分享6个经典机器学习项目,涵盖回归、分类、文本分析、聚类、半监督和自监督学习等多个方向。这些项目不仅适合初学者构建知识体系,也能帮助有经验的开发者拓展技术视野。

2. 回归任务:加州房价预测

2.1 项目概述与数据准备

房价预测是机器学习入门的经典回归问题。我们使用Scikit-learn内置的California Housing数据集,包含20,640个样本和8个特征:

  • MedInc:街区收入中位数
  • HouseAge:房屋年龄中位数
  • AveRooms:平均房间数
  • AveBedrms:平均卧室数
  • Population:街区人口
  • AveOccup:平均入住率
  • Latitude:纬度
  • Longitude:经度
from sklearn.datasets import fetch_california_housing import pandas as pd data = fetch_california_housing() X, y = data.data, data.target df = pd.DataFrame(X, columns=data.feature_names) df['MedHouseVal'] = y print(df.head())

2.2 完整建模流程

2.2.1 数据预处理与划分
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) # 特征标准化(线性模型需要) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)
2.2.2 模型训练与评估

我们比较线性回归和随机森林两种算法:

from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, r2_score import numpy as np models = { 'Linear Regression': LinearRegression(), 'Random Forest': RandomForestRegressor(n_estimators=100, random_state=42) } results = {} for name, model in models.items(): # 线性模型用缩放数据,树模型用原始数据 X_tr = X_train_scaled if name == 'Linear Regression' else X_train X_te = X_test_scaled if name == 'Linear Regression' else X_test model.fit(X_tr, y_train) y_pred = model.predict(X_te) rmse = np.sqrt(mean_squared_error(y_test, y_pred)) r2 = r2_score(y_test, y_pred) results[name] = {'RMSE': rmse, 'R²': r2} print(f"{name} → RMSE: {rmse:.2f}, R²: {r2:.2%}")
2.2.3 模型优化

对随机森林进行超参数调优:

from sklearn.model_selection import RandomizedSearchCV from scipy.stats import randint param_dist = { 'n_estimators': randint(50, 200), 'max_depth': [3, 5, 7, 10, None], 'min_samples_split': randint(2, 20) } rf = RandomForestRegressor(random_state=42) random_search = RandomizedSearchCV( rf, param_dist, n_iter=20, cv=5, scoring='neg_root_mean_squared_error', n_jobs=-1 ) random_search.fit(X_train, y_train) print("\n优化后参数:", random_search.best_params_) best_rf = random_search.best_estimator_ y_pred_best = best_rf.predict(X_test) print(f"优化后 RMSE: {np.sqrt(mean_squared_error(y_test, y_pred_best)):.2f}")

关键经验:

  1. 树模型不需要特征缩放,但线性模型对特征尺度敏感
  2. 随机搜索比网格搜索更高效,特别是参数空间较大时
  3. 房价预测中,地理位置特征(经纬度)往往最重要

3. 分类任务:客户流失预测

3.1 业务理解与数据模拟

客户流失预测是典型的二分类问题。我们使用电信行业数据集(模拟数据):

import numpy as np import pandas as pd np.random.seed(42) n = 7000 df = pd.DataFrame({ 'tenure': np.random.randint(1, 73, n), # 在网月数 'MonthlyCharges': np.random.uniform(20, 120, n), 'TotalCharges': lambda x: x['tenure'] * x['MonthlyCharges'], 'gender': np.random.choice(['Male', 'Female'], n), 'Partner': np.random.choice(['Yes', 'No'], n), 'Dependents': np.random.choice(['Yes', 'No'], n), 'Churn': np.random.binomial(1, 0.25, n) # 目标变量 })

3.2 分类建模流程

3.2.1 数据预处理
from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline # 分离数值和类别特征 num_features = ['tenure', 'MonthlyCharges', 'TotalCharges'] cat_features = ['gender', 'Partner', 'Dependents'] # 构建预处理管道 preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), num_features), ('cat', OneHotEncoder(drop='first'), cat_features) ] )
3.2.2 模型训练与评估
from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report # 划分数据集 X = df.drop('Churn', axis=1) y = df['Churn'] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42 ) # 定义模型管道 models = { 'Logistic Regression': Pipeline([ ('preprocessor', preprocessor), ('classifier', LogisticRegression(max_iter=1000)) ]), 'Random Forest': Pipeline([ ('preprocessor', preprocessor), ('classifier', RandomForestClassifier(n_estimators=100, random_state=42)) ]) } # 训练与评估 for name, pipeline in models.items(): pipeline.fit(X_train, y_train) y_pred = pipeline.predict(X_test) print(f"\n{name} 分类报告:") print(classification_report(y_test, y_pred))

关键经验:

  1. 分类任务关注精确率、召回率和F1值,而不仅仅是准确率
  2. 使用stratify=y保证训练/测试集标签分布一致
  3. 类别特征使用One-Hot编码时,drop='first'可避免多重共线性

4. 文本情感分析

4.1 文本数据准备

我们使用20 Newsgroups数据集模拟情感分析任务:

from sklearn.datasets import fetch_20newsgroups categories = ['alt.atheism', 'soc.religion.christian'] newsgroups_train = fetch_20newsgroups(subset='train', categories=categories) newsgroups_test = fetch_20newsgroups(subset='test', categories=categories) X_train_text, y_train = newsgroups_train.data, newsgroups_train.target X_test_text, y_test = newsgroups_test.data, newsgroups_test.target

4.2 文本特征工程与建模

4.2.1 TF-IDF向量化
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.svm import SVC from sklearn.metrics import accuracy_score # 文本向量化 vectorizer = TfidfVectorizer( max_features=5000, # 限制词汇表大小 stop_words='english', # 去除停用词 ngram_range=(1, 2) # 使用1-gram和2-gram ) X_train_tfidf = vectorizer.fit_transform(X_train_text) X_test_tfidf = vectorizer.transform(X_test_text)
4.2.2 模型比较
models = { 'Naive Bayes': MultinomialNB(alpha=0.1), 'SVM': SVC(kernel='linear', C=1.0) } for name, model in models.items(): model.fit(X_train_tfidf, y_train) y_pred = model.predict(X_test_tfidf) acc = accuracy_score(y_test, y_pred) print(f"{name} 准确率: {acc:.2%}")
4.2.3 关键词分析
# 查看朴素贝叶斯模型学习到的重要特征 nb = MultinomialNB() nb.fit(X_train_tfidf, y_train) feature_names = vectorizer.get_feature_names_out() # 获取各类别的高权重词 for i, class_name in enumerate(newsgroups_train.target_names): top_features = np.argsort(nb.coef_[i])[-10:] print(f"\n{class_name} 关键词:", [feature_names[j] for j in top_features])

关键经验:

  1. ngram_range=(1,2)可以捕捉短语信息(如"not good")
  2. 朴素贝叶斯适合高维稀疏文本数据
  3. 线性SVM在文本分类中通常表现优异
  4. 停用词去除和最大特征数限制对性能影响很大

5. 无监督学习:用户分群

5.1 数据模拟与预处理

我们模拟电商用户行为数据:

import numpy as np import pandas as pd np.random.seed(42) n_users = 2000 df_users = pd.DataFrame({ 'age': np.random.randint(18, 70, n_users), 'income': np.random.exponential(50000, n_users), 'purchase_freq': np.random.poisson(5, n_users), 'avg_order_value': np.random.gamma(2, 50, n_users) })

5.2 聚类分析流程

5.2.1 数据标准化
from sklearn.preprocessing import StandardScaler X = df_users.values scaler = StandardScaler() X_scaled = scaler.fit_transform(X)
5.2.2 确定最佳聚类数
from sklearn.cluster import KMeans import matplotlib.pyplot as plt inertias = [] K_range = range(2, 10) for k in K_range: kmeans = KMeans(n_clusters=k, random_state=42) kmeans.fit(X_scaled) inertias.append(kmeans.inertia_) plt.plot(K_range, inertias, 'bo-') plt.xlabel('K') plt.ylabel('Inertia') plt.title('Elbow Method') plt.show()
5.2.3 执行聚类与分析
# 选择K=4执行聚类 kmeans = KMeans(n_clusters=4, random_state=42) clusters = kmeans.fit_predict(X_scaled) df_users['cluster'] = clusters # 分析聚类结果 print(df_users.groupby('cluster').mean()) # 可视化(PCA降维) from sklearn.decomposition import PCA pca = PCA(n_components=2) X_pca = pca.fit_transform(X_scaled) plt.scatter(X_pca[:, 0], X_pca[:, 1], c=clusters, cmap='viridis') plt.title("用户分群 (PCA可视化)") plt.show()

关键经验:

  1. 聚类前必须标准化,消除不同特征量纲影响
  2. 肘部法则和轮廓系数是确定K值的常用方法
  3. 高维数据可视化前通常需要降维(PCA/t-SNE)
  4. 业务解释是聚类分析中最关键的环节

6. 半监督学习:文本分类

6.1 半监督数据准备

我们使用部分标注的20 Newsgroups数据:

from sklearn.datasets import fetch_20newsgroups import numpy as np # 加载全部数据 all_data = fetch_20newsgroups(subset='all', categories=['comp.graphics', 'sci.med']) X_text_all, y_all = all_data.data, all_data.target # 模拟:仅5%有标签 np.random.seed(42) n_total = len(y_all) n_labeled = int(0.05 * n_total) labeled_idx = np.random.choice(n_total, size=n_labeled, replace=False) y_semi = np.full(n_total, -1) # -1表示无标签 y_semi[labeled_idx] = y_all[labeled_idx]

6.2 伪标签法实现

6.2.1 初始模型训练
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression # 文本向量化 vectorizer = TfidfVectorizer(max_features=3000, stop_words='english') X_tfidf = vectorizer.fit_transform(X_text_all) # 仅用有标签数据训练初始模型 X_labeled = X_tfidf[labeled_idx] y_labeled = y_all[labeled_idx] lr = LogisticRegression(max_iter=1000) lr.fit(X_labeled, y_labeled)
6.2.2 生成伪标签
# 预测所有样本的概率 proba = lr.predict_proba(X_tfidf) pseudo_labels = lr.predict(X_tfidf) # 选择高置信度预测作为伪标签 high_conf = proba.max(axis=1) > 0.9 # 置信度阈值 # 构建增强训练集 train_idx = np.concatenate([labeled_idx, np.where(high_conf)[0]]) y_train = np.concatenate([y_labeled, pseudo_labels[high_conf]])
6.2.3 联合训练与评估
# 在增强数据集上训练最终模型 lr_final = LogisticRegression(max_iter=1000) lr_final.fit(X_tfidf[train_idx], y_train) # 评估(假设我们有完整测试集) test_acc = lr_final.score(X_tfidf, y_all) print(f"半监督准确率: {test_acc:.2%}") # 对比纯监督学习 lr_baseline = LogisticRegression(max_iter=1000) lr_baseline.fit(X_labeled, y_labeled) baseline_acc = lr_baseline.score(X_tfidf, y_all) print(f"纯监督 (5%标签) 准确率: {baseline_acc:.2%}")

关键经验:

  1. 置信度阈值控制伪标签质量,通常设置在0.8-0.95
  2. 可以迭代进行多轮伪标签生成和模型训练
  3. 半监督学习在标注数据稀缺时特别有效
  4. 文本和图像等高维数据最适合半监督方法

7. 自监督学习:图像特征提取

7.1 数据准备

我们使用MNIST数据集模拟自监督学习场景:

from sklearn.datasets import fetch_openml mnist = fetch_openml('mnist_784', version=1, as_frame=False) X, y = mnist.data / 255.0, mnist.target.astype(int) # 模拟:60000张无标注,仅1000张有标注 X_unlabeled = X[:60000] X_labeled = X[60000:61000] y_labeled = y[60000:61000] X_test, y_test = X[61000:], y[61000:]

7.2 自编码器预训练

7.2.1 自监督预训练
from sklearn.neural_network import MLPRegressor # 自编码器结构:784 → 128 → 64 → 128 → 784 autoencoder = MLPRegressor( hidden_layer_sizes=(128, 64, 128), activation='relu', solver='adam', max_iter=30, random_state=42 ) # 自监督训练:输入=输出 autoencoder.fit(X_unlabeled, X_unlabeled)
7.2.2 特征提取与分类
from sklearn.decomposition import PCA from sklearn.linear_model import LogisticRegression # 使用PCA模拟自编码器中间层特征 pca = PCA(n_components=64) pca.fit(X_unlabeled) # 提取特征 X_labeled_features = pca.transform(X_labeled) X_test_features = pca.transform(X_test) # 在少量标注数据上训练分类器 clf = LogisticRegression(max_iter=1000) clf.fit(X_labeled_features, y_labeled) # 评估 test_acc = clf.score(X_test_features, y_test) print(f"自监督特征 + 线性分类器准确率: {test_acc:.2%}") # 对比无预训练 clf_raw = LogisticRegression(max_iter=1000) clf_raw.fit(X_labeled, y_labeled) raw_acc = clf_raw.score(X_test, y_test) print(f"无预训练准确率: {raw_acc:.2%}")

关键经验:

  1. 自监督学习可以利用大量无标注数据学习通用特征
  2. 预训练后,少量标注数据即可达到较好分类效果
  3. 实际项目中推荐使用PyTorch实现更复杂的自监督算法
  4. 自监督特征通常比手工设计特征更具泛化能力

8. 项目选择与实践建议

8.1 项目选择指南

项目类型适用场景推荐算法关键技能
房价预测回归问题线性回归、随机森林特征工程、RMSE评估
客户流失二分类逻辑回归、XGBoost类别编码、不平衡处理
情感分析文本分类朴素贝叶斯、SVMTF-IDF、N-gram
用户分群客户洞察K-Means、DBSCAN标准化、肘部法则
半监督分类标注稀缺伪标签 + LR/RF置信度过滤、迭代训练
自监督图像冷启动问题自编码器/对比学习 + 线性分类预训练、特征提取

8.2 实践建议

  1. 模型部署:

    • 使用joblib或pickle保存训练好的模型
    • 通过Flask或FastAPI提供预测API
    • 考虑使用ONNX格式实现跨平台部署
  2. 生产监控:

    • 跟踪数据漂移(Data Drift)
    • 监控预测分布变化
    • 设置模型性能报警阈值
  3. MLOps实践:

    • 使用MLflow跟踪实验
    • 实现持续集成/持续部署(CI/CD)
    • 建立模型版本控制和回滚机制
  4. 性能优化:

    • 对树模型使用GPU加速
    • 对线性模型使用稀疏矩阵
    • 考虑模型量化减小内存占用

在实际项目中,我经常发现数据质量比算法选择更重要。花时间做好数据探索和清洗,通常能带来比调参更大的性能提升。另外,模型的可解释性在业务场景中往往比绝对精度更重要 - 一个能被业务方理解的简单模型,通常比黑箱的复杂模型更有实用价值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询