人工智能之核心基础 机器学习
第十八章 经典实战项目
文章目录
- [人工智能之核心基础 机器学习](#人工智能之核心基础 机器学习)
- [18.1 入门项目1:房价预测(回归任务)](#18.1 入门项目1:房价预测(回归任务))
- [🎯 任务目标](#🎯 任务目标)
- [📦 数据集:`California Housing`(Scikit-learn内置)](#📦 数据集:
California Housing(Scikit-learn内置))- [🔧 完整流程](#🔧 完整流程)
- [18.2 入门项目2:客户流失预测(分类任务)](#18.2 入门项目2:客户流失预测(分类任务))
- [🎯 任务目标](#🎯 任务目标)
- [📦 数据集:[Telco Customer Churn](https://www.kaggle.com/blastchar/telco-customer-churn)(简化版)](#📦 数据集:Telco Customer Churn(简化版))
- [🔧 完整流程](#🔧 完整流程)
- [18.3 进阶项目1:文本情感分析](#18.3 进阶项目1:文本情感分析)
- [🎯 任务目标](#🎯 任务目标)
- [📦 数据集:`IMDB` 或 `Movie Reviews`(使用 Scikit-learn 内置)](#📦 数据集:
IMDB或Movie Reviews(使用 Scikit-learn 内置))- [🔧 文本处理全流程](#🔧 文本处理全流程)
- [18.4 进阶项目2:用户分群(无监督)](#18.4 进阶项目2:用户分群(无监督))
- [🎯 任务目标](#🎯 任务目标)
- [📦 数据:电商用户行为(模拟)](#📦 数据:电商用户行为(模拟))
- [🔧 聚类全流程](#🔧 聚类全流程)
- [18.5 进阶项目3:半监督文本分类](#18.5 进阶项目3:半监督文本分类)
- [🎯 任务目标](#🎯 任务目标)
- [📦 数据:20 Newsgroups(部分标注)](#📦 数据:20 Newsgroups(部分标注))
- [🔧 伪标签法全流程](#🔧 伪标签法全流程)
- [18.6 进阶项目4:自监督图像特征提取与分类](#18.6 进阶项目4:自监督图像特征提取与分类)
- [🎯 任务目标](#🎯 任务目标)
- [📦 数据:MNIST(模拟无标注+少量标注)](#📦 数据:MNIST(模拟无标注+少量标注))
- [🔧 自编码器预训练 + 微调](#🔧 自编码器预训练 + 微调)
- [🎯 本章终极总结:项目选择指南](#🎯 本章终极总结:项目选择指南)
- 资料关注
18.1 入门项目1:房价预测(回归任务)
🎯 任务目标
根据房屋特征(面积、房间数、位置等)预测价格。
📦 数据集:California Housing(Scikit-learn内置)
python
# 1. 加载数据
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())
🔧 完整流程
python
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
# 2. 划分数据
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 3. 特征缩放(线性模型需要)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 4. 模型训练与评估
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%}")
# 5. 模型优化(以随机森林为例)
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}")
💡 关键点:
- 回归任务评估:RMSE (越小越好)、R²(越接近1越好)
- 树模型不需要特征缩放
- 随机搜索比网格搜索更高效
18.2 入门项目2:客户流失预测(分类任务)
🎯 任务目标
预测电信用户是否会流失(0/1分类)。
📦 数据集:Telco Customer Churn(简化版)
python
# 模拟数据生成(实际项目请下载真实数据)
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) # 目标变量
})
🔧 完整流程
python
from sklearn.preprocessing import LabelEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
# 1. 数据预处理
# 分离数值和类别特征
num_features = ['tenure', 'MonthlyCharges', 'TotalCharges']
cat_features = ['gender', 'Partner', 'Dependents']
# 构建预处理管道
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), num_features),
('cat', OneHotEncoder(drop='first'), cat_features)
]
)
# 2. 划分数据
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
)
# 3. 模型管道
models = {
'Logistic Regression': Pipeline([
('preprocessor', preprocessor),
('classifier', LogisticRegression(max_iter=1000))
]),
'Random Forest': Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])
}
# 4. 训练与评估
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))
💡 关键点:
- 分类任务关注精确率、召回率、F1值
- 使用
stratify=y保证训练/测试集标签分布一致- 类别特征用 One-Hot 编码(Drop first 防多重共线性)
18.3 进阶项目1:文本情感分析
🎯 任务目标
判断电影评论是正面还是负面。
📦 数据集:IMDB 或 Movie Reviews(使用 Scikit-learn 内置)
python
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
🔧 文本处理全流程
python
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.svm import SVC
# 1. 文本向量化(TF-IDF)
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)
# 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%}")
# 3. 查看重要特征(以NB为例)
nb = MultinomialNB()
nb.fit(X_train_tfidf, y_train)
feature_names = vectorizer.get_feature_names_out()
# 正面类(假设label=1)的高权重词
pos_coef = nb.coef_[0]
top_pos = np.argsort(pos_coef)[-10:]
print("\n正面关键词:", [feature_names[i] for i in top_pos])
💡 关键点:
- 文本需向量化:TF-IDF 是经典方法
- 朴素贝叶斯适合高维稀疏文本
- SVM 在文本分类中表现优异
ngram_range=(1,2)捕捉短语信息(如 "not good")
18.4 进阶项目2:用户分群(无监督)
🎯 任务目标
根据用户行为将客户分为不同群体。
📦 数据:电商用户行为(模拟)
python
# 模拟用户数据
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)
})
🔧 聚类全流程
python
from sklearn.cluster import KMeans, DBSCAN
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# 1. 数据预处理
X = df_users.values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 2. 确定K值(肘部法则)
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() # 假设选择 K=4
# 3. 执行聚类
kmeans = KMeans(n_clusters=4, random_state=42)
clusters = kmeans.fit_predict(X_scaled)
df_users['cluster'] = clusters
# 4. 分析聚类结果
print(df_users.groupby('cluster').mean())
# 5. 可视化(PCA降维到2D)
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()
💡 关键点:
- 聚类前必须标准化(不同量纲)
- 肘部法则选K,或用轮廓系数
- DBSCAN 适合不规则形状簇,但需调
eps和min_samples
18.5 进阶项目3:半监督文本分类
🎯 任务目标
仅用少量标注评论 + 大量无标注评论,训练高精度分类器。
📦 数据:20 Newsgroups(部分标注)
python
# 加载全部数据
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)
y_semi[labeled_idx] = y_all[labeled_idx]
🔧 伪标签法全流程
python
# 1. 文本向量化
vectorizer = TfidfVectorizer(max_features=3000, stop_words='english')
X_tfidf = vectorizer.fit_transform(X_text_all)
# 2. 初始模型训练(仅用有标签数据)
X_labeled = X_tfidf[labeled_idx]
y_labeled = y_all[labeled_idx]
lr = LogisticRegression(max_iter=1000)
lr.fit(X_labeled, y_labeled)
# 3. 生成伪标签
proba = lr.predict_proba(X_tfidf)
pseudo_labels = lr.predict(X_tfidf)
high_conf = proba.max(axis=1) > 0.9 # 高置信度
# 4. 构建增强训练集
train_idx = np.concatenate([labeled_idx, np.where(high_conf)[0]])
y_train = np.concatenate([y_labeled, pseudo_labels[high_conf]])
# 5. 联合训练
lr_final = LogisticRegression(max_iter=1000)
lr_final.fit(X_tfidf[train_idx], y_train)
# 6. 评估(假设我们有完整测试集)
# 实际中可用交叉验证或保留部分标注数据
test_acc = lr_final.score(X_tfidf, y_all)
print(f"半监督准确率: {test_acc:.2%}")
# 对比:仅用5%标签的监督学习
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%}")
💡 关键点:
- 置信度阈值控制伪标签质量
- 可迭代:多次生成伪标签 → 再训练
- 适用于文本、图像等高维数据
18.6 进阶项目4:自监督图像特征提取与分类
🎯 任务目标
用大量无标注图像预训练特征提取器,再用少量标注数据做分类。
📦 数据:MNIST(模拟无标注+少量标注)
python
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:]
🔧 自编码器预训练 + 微调
python
from sklearn.neural_network import MLPRegressor
from sklearn.linear_model import LogisticRegression
# 步骤1: 自监督预训练(自编码器)
autoencoder = MLPRegressor(
hidden_layer_sizes=(128, 64, 128),
activation='relu',
solver='adam',
max_iter=30,
random_state=42
)
# 训练:输入=输出
autoencoder.fit(X_unlabeled, X_unlabeled)
# 步骤2: 提取编码器特征(中间层)
# 注意:sklearn MLP 不直接暴露中间层,需手动实现或用PyTorch
# 此处用PCA近似(实际项目建议用深度框架)
from sklearn.decomposition import PCA
pca = PCA(n_components=64)
pca.fit(X_unlabeled) # 模拟自监督学到的特征
X_labeled_features = pca.transform(X_labeled)
X_test_features = pca.transform(X_test)
# 步骤3: 少量标注数据上训练分类器
clf = LogisticRegression(max_iter=1000)
clf.fit(X_labeled_features, y_labeled)
# 步骤4: 评估
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%}")
💡 现实做法(推荐):
- 用 PyTorch 实现 SimSiam 或 MAE 进行预训练
- 提取 backbone 特征
- 用 Scikit-learn 训练 SVM/Logistic Regression 做下游分类
python
# 伪代码(实际需深度学习框架)
# features = sim_siam_encoder(unlabeled_images) # 自监督预训练
# clf = LogisticRegression().fit(features[labeled_idx], y_labeled)
# acc = clf.score(features[test_idx], y_test)
✅ 优势 :
在1000个标签上,自监督预训练可提升准确率 10~20%!
🎯 本章终极总结:项目选择指南
| 项目类型 | 适用场景 | 推荐算法 | 关键技能 |
|---|---|---|---|
| 房价预测 | 回归问题 | 线性回归、随机森林 | 特征工程、RMSE评估 |
| 客户流失 | 二分类 | 逻辑回归、XGBoost | 类别编码、不平衡处理 |
| 情感分析 | 文本分类 | 朴素贝叶斯、SVM | TF-IDF、N-gram |
| 用户分群 | 客户洞察 | K-Means、DBSCAN | 标准化、肘部法则 |
| 半监督分类 | 标注稀缺 | 伪标签 + LR/RF | 置信度过滤、迭代训练 |
| 自监督图像 | 冷启动 | 自编码器/对比学习 + 线性分类 | 预训练、特征提取 |
📘 建议:
- 部署 :用
joblib保存模型,Flask/Django 提供API - 监控:跟踪数据漂移(Data Drift)
- MLOps:MLflow 跟踪实验
资料关注
公众号:咚咚王
gitee:https://gitee.com/wy18585051844/ai_learning
《Python编程:从入门到实践》
《利用Python进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第3版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow机器学习实战指南》
《Sklearn与TensorFlow机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》
《自然语言处理综论 第2版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨+&+张孜铭
《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战AI大模型》
《AI 3.0》