欢迎来到第二周的学习!在第一周我们了解了AI的基础知识和早期案例,今天我们将深入学习传统机器学习模型,从最基础的线性回归到强大的XGBoost,带你全面掌握这些经典但仍然非常实用的算法。
传统机器学习概览
传统机器学习是现代AI技术的重要基石,虽然深度学习在许多领域取得了突破性进展,但传统机器学习算法在许多场景下仍然表现出色,尤其是在数据量有限或特征工程充分的情况下。
graph TD
A[机器学习] --> B[监督学习]
A --> C[无监督学习]
A --> D[强化学习]
B --> E[回归]
B --> F[分类]
C --> G[聚类]
C --> H[降维]
监督学习基础
监督学习是机器学习中最常见的类型,它使用带有标签的数据进行训练。
回归 vs 分类
- 回归任务:预测连续值(如房价、温度)
- 分类任务:预测离散类别(如垃圾邮件识别、图像分类)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = 2 * X.ravel() + 1 + np.random.normal(0, 2, 100) # y = 2x + 1 + 噪声
# 可视化数据
plt.figure(figsize=(10, 6))
plt.scatter(X, y, alpha=0.6)
plt.xlabel('特征 X')
plt.ylabel('目标值 y')
plt.title('回归问题示例数据')
plt.grid(True, alpha=0.3)
plt.show()
print(f"数据形状: X={X.shape}, y={y.shape}")
print("这是一个典型的回归问题,目标是预测连续值")
分类任务示例
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
import seaborn as sns
# 生成分类数据
X_class, y_class = make_classification(
n_samples=200,
n_features=2,
n_redundant=0,
n_informative=2,
n_clusters_per_class=1,
random_state=42
)
# 可视化分类数据
plt.figure(figsize=(10, 6))
plt.scatter(X_class[:, 0], X_class[:, 1], c=y_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('分类问题示例数据')
plt.colorbar(label='类别')
plt.grid(True, alpha=0.3)
plt.show()
print(f"分类数据形状: X={X_class.shape}, y={y_class.shape}")
print(f"类别数量: {len(np.unique(y_class))}")
print("这是一个二分类问题,目标是将数据分为两个类别")
线性模型详解
线性模型是机器学习中最基础也是最重要的模型之一,包括线性回归和逻辑回归。
线性回归
线性回归用于解决回归问题,假设目标值与特征之间存在线性关系。
# 线性回归实现
class SimpleLinearRegression:
"""简单线性回归实现"""
def __init__(self):
self.slope = None
self.intercept = None
def fit(self, X, y):
"""训练模型"""
X = X.ravel() # 确保X是一维的
x_mean = np.mean(X)
y_mean = np.mean(y)
# 计算斜率和截距
numerator = np.sum((X - x_mean) * (y - y_mean))
denominator = np.sum((X - x_mean) ** 2)
self.slope = numerator / denominator
self.intercept = y_mean - self.slope * x_mean
def predict(self, X):
"""预测"""
return self.slope * X.ravel() + self.intercept
# 使用自定义线性回归
custom_lr = SimpleLinearRegression()
custom_lr.fit(X, y)
y_pred_custom = custom_lr.predict(X)
# 使用sklearn线性回归
sklearn_lr = LinearRegression()
sklearn_lr.fit(X, y)
y_pred_sklearn = sklearn_lr.predict(X)
# 比较结果
print("自定义线性回归:")
print(f"斜率: {custom_lr.slope:.4f}")
print(f"截距: {custom_lr.intercept:.4f}")
print("\nSklearn线性回归:")
print(f"斜率: {sklearn_lr.coef_[0]:.4f}")
print(f"截距: {sklearn_lr.intercept_:.4f}")
# 计算评估指标
mse_custom = mean_squared_error(y, y_pred_custom)
r2_custom = r2_score(y, y_pred_custom)
mse_sklearn = mean_squared_error(y, y_pred_sklearn)
r2_sklearn = r2_score(y, y_pred_sklearn)
print(f"\n自定义模型 - MSE: {mse_custom:.4f}, R²: {r2_custom:.4f}")
print(f"Sklearn模型 - MSE: {mse_sklearn:.4f}, R²: {r2_sklearn:.4f}")
# 可视化结果
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.scatter(X, y, alpha=0.6, label='原始数据')
plt.plot(X, y_pred_custom, 'r-', linewidth=2, label=f'拟合直线 (y={custom_lr.slope:.2f}x+{custom_lr.intercept:.2f})')
plt.xlabel('X')
plt.ylabel('y')
plt.title('自定义线性回归')
plt.legend()
plt.grid(True, alpha=0.3)
plt.subplot(1, 2, 2)
plt.scatter(X, y, alpha=0.6, label='原始数据')
plt.plot(X, y_pred_sklearn, 'g-', linewidth=2, label=f'拟合直线 (y={sklearn_lr.coef_[0]:.2f}x+{sklearn_lr.intercept_:.2f})')
plt.xlabel('X')
plt.ylabel('y')
plt.title('Sklearn线性回归')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
逻辑回归
逻辑回归用于解决分类问题,通过sigmoid函数将线性回归的输出映射到0-1之间。
# 逻辑回归实现
class SimpleLogisticRegression:
"""简单逻辑回归实现"""
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None
def sigmoid(self, z):
"""Sigmoid函数"""
# 防止溢出
z = np.clip(z, -500, 500)
return 1 / (1 + np.exp(-z))
def fit(self, X, y):
"""训练模型"""
n_samples, n_features = X.shape
# 初始化参数
self.weights = np.zeros(n_features)
self.bias = 0
# 梯度下降
for i in range(self.n_iterations):
# 前向传播
linear_pred = np.dot(X, self.weights) + self.bias
predictions = self.sigmoid(linear_pred)
# 计算损失
loss = (-1/n_samples) * np.sum(y*np.log(predictions) + (1-y)*np.log(1-predictions))
# 计算梯度
dw = (1/n_samples) * np.dot(X.T, (predictions - y))
db = (1/n_samples) * np.sum(predictions - y)
# 更新参数
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
def predict(self, X):
"""预测概率"""
linear_pred = np.dot(X, self.weights) + self.bias
return self.sigmoid(linear_pred)
def predict_class(self, X, threshold=0.5):
"""预测类别"""
probabilities = self.predict(X)
return (probabilities >= threshold).astype(int)
# 使用逻辑回归进行分类
X_train, X_test, y_train, y_test = train_test_split(
X_class, y_class, test_size=0.3, random_state=42
)
# 自定义逻辑回归
custom_log_reg = SimpleLogisticRegression(learning_rate=0.1, n_iterations=1000)
custom_log_reg.fit(X_train, y_train)
y_pred_proba = custom_log_reg.predict(X_test)
y_pred_class = custom_log_reg.predict_class(X_test)
# Sklearn逻辑回归
sklearn_log_reg = LogisticRegression()
sklearn_log_reg.fit(X_train, y_train)
sklearn_pred_proba = sklearn_log_reg.predict_proba(X_test)[:, 1]
sklearn_pred_class = sklearn_log_reg.predict(X_test)
# 计算准确率
from sklearn.metrics import accuracy_score
custom_accuracy = accuracy_score(y_test, y_pred_class)
sklearn_accuracy = accuracy_score(y_test, sklearn_pred_class)
print("逻辑回归分类结果:")
print(f"自定义模型准确率: {custom_accuracy:.4f}")
print(f"Sklearn模型准确率: {sklearn_accuracy:.4f}")
# 可视化分类结果
plt.figure(figsize=(15, 5))
# 原始数据
plt.subplot(1, 3, 1)
plt.scatter(X_class[:, 0], X_class[:, 1], c=y_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('原始分类数据')
plt.colorbar(label='真实类别')
# 自定义逻辑回归结果
plt.subplot(1, 3, 2)
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title(f'自定义逻辑回归\n准确率: {custom_accuracy:.4f}')
plt.colorbar(label='预测类别')
# Sklearn逻辑回归结果
plt.subplot(1, 3, 3)
plt.scatter(X_test[:, 0], X_test[:, 1], c=sklearn_pred_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title(f'Sklearn逻辑回归\n准确率: {sklearn_accuracy:.4f}')
plt.colorbar(label='预测类别')
plt.tight_layout()
plt.show()
决策树与集成学习
决策树是一种基于树结构的分类和回归模型,易于理解和解释。集成学习通过组合多个模型来提高性能。
决策树
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
iris = load_iris()
X_iris, y_iris = iris.data, iris.target
# 创建决策树
dt_classifier = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_classifier.fit(X_iris, y_iris)
# 预测
y_pred_iris = dt_classifier.predict(X_iris)
# 计算准确率
accuracy_iris = accuracy_score(y_iris, y_pred_iris)
print(f"决策树在鸢尾花数据集上的准确率: {accuracy_iris:.4f}")
# 可视化决策树
plt.figure(figsize=(15, 10))
plot_tree(dt_classifier,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True,
rounded=True,
fontsize=10)
plt.title('鸢尾花分类决策树')
plt.show()
# 特征重要性
feature_importance = dt_classifier.feature_importances_
plt.figure(figsize=(10, 6))
plt.bar(range(len(feature_importance)), feature_importance)
plt.xlabel('特征')
plt.ylabel('重要性')
plt.title('决策树特征重要性')
plt.xticks(range(len(feature_importance)), iris.feature_names, rotation=45)
plt.tight_layout()
plt.show()
for i, importance in enumerate(feature_importance):
print(f"{iris.feature_names[i]}: {importance:.4f}")
随机森林
随机森林是一种集成学习方法,通过组合多个决策树来提高性能。
from sklearn.ensemble import RandomForestClassifier
# 创建随机森林
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
rf_classifier.fit(X_iris, y_iris)
# 预测
y_pred_rf = rf_classifier.predict(X_iris)
# 计算准确率
accuracy_rf = accuracy_score(y_iris, y_pred_rf)
print(f"随机森林在鸢尾花数据集上的准确率: {accuracy_rf:.4f}")
# 特征重要性
rf_feature_importance = rf_classifier.feature_importances_
plt.figure(figsize=(10, 6))
plt.bar(range(len(rf_feature_importance)), rf_feature_importance)
plt.xlabel('特征')
plt.ylabel('重要性')
plt.title('随机森林特征重要性')
plt.xticks(range(len(rf_feature_importance)), iris.feature_names, rotation=45)
plt.tight_layout()
plt.show()
for i, importance in enumerate(rf_feature_importance):
print(f"{iris.feature_names[i]}: {importance:.4f}")
XGBoost
XGBoost是一种强大的梯度提升算法,在许多机器学习竞赛中表现出色。
# 注意:需要先安装xgboost: pip install xgboost
try:
import xgboost as xgb
# 创建XGBoost分类器
xgb_classifier = xgb.XGBClassifier(
n_estimators=100,
max_depth=3,
learning_rate=0.1,
random_state=42
)
xgb_classifier.fit(X_iris, y_iris)
# 预测
y_pred_xgb = xgb_classifier.predict(X_iris)
# 计算准确率
accuracy_xgb = accuracy_score(y_iris, y_pred_xgb)
print(f"XGBoost在鸢尾花数据集上的准确率: {accuracy_xgb:.4f}")
# 特征重要性
xgb_feature_importance = xgb_classifier.feature_importances_
plt.figure(figsize=(10, 6))
plt.bar(range(len(xgb_feature_importance)), xgb_feature_importance)
plt.xlabel('特征')
plt.ylabel('重要性')
plt.title('XGBoost特征重要性')
plt.xticks(range(len(xgb_feature_importance)), iris.feature_names, rotation=45)
plt.tight_layout()
plt.show()
for i, importance in enumerate(xgb_feature_importance):
print(f"{iris.feature_names[i]}: {importance:.4f}")
except ImportError:
print("未安装xgboost,请使用 'pip install xgboost' 安装")
print("XGBoost是一种强大的梯度提升算法,在Kaggle等数据科学竞赛中广泛使用")
模型评估指标
选择合适的评估指标对于模型性能评估至关重要。
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
# 使用分类报告详细评估模型
print("分类报告:")
print(classification_report(y_test, y_pred_class, target_names=['类别 0', '类别 1']))
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred_class)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['预测 0', '预测 1'],
yticklabels=['实际 0', '实际 1'])
plt.title('混淆矩阵')
plt.ylabel('实际类别')
plt.xlabel('预测类别')
plt.show()
# 回归评估指标
print("回归模型评估指标:")
print(f"MSE (均方误差): {mean_squared_error(y, y_pred_sklearn):.4f}")
print(f"RMSE (均方根误差): {np.sqrt(mean_squared_error(y, y_pred_sklearn)):.4f}")
print(f"R² (决定系数): {r2_score(y, y_pred_sklearn):.4f}")
print(f"MAE (平均绝对误差): {np.mean(np.abs(y - y_pred_sklearn)):.4f}")
本周学习总结
今天我们全面学习了传统机器学习模型:
-
监督学习基础
- 理解了回归和分类任务的区别
- 学会了数据可视化和基本概念
-
线性模型
- 实现了线性回归和逻辑回归
- 理解了模型的工作原理和数学基础
-
决策树与集成学习
- 学习了决策树的结构和工作原理
- 掌握了随机森林等集成学习方法
- 了解了XGBoost的强大功能
-
模型评估
- 学习了准确率、混淆矩阵等评估指标
- 掌握了回归和分类任务的评估方法
graph TD
A[传统机器学习] --> B[监督学习]
A --> C[模型评估]
B --> D[线性模型]
B --> E[树模型]
B --> F[集成学习]
D --> G[线性回归]
D --> H[逻辑回归]
E --> I[决策树]
F --> J[随机森林]
F --> K[XGBoost]
课后练习
- 运行本节所有代码示例,理解每种算法的特点
- 尝试调整模型参数(如决策树深度、随机森林树的数量等),观察性能变化
- 在不同的数据集上测试这些算法,比较它们的表现
- 实现一个简单的模型比较函数,自动评估多个模型在相同数据上的性能
下节预告
下一节我们将学习无监督学习算法,包括K-Means聚类和PCA降维技术,这些方法在数据分析和特征工程中非常重要,敬请期待!
有任何疑问请在讨论区留言,我们会定期回复大家的问题。