一、线性回归
级别1:简单一元线性回归(手工实现)
import numpy as np
import matplotlib.pyplot as plt
# 生成数据
X = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])
# 手动实现梯度下降
def gradient_descent(X, y, lr=0.01, epochs=1000):
w, b = 0, 0 # 初始化参数
n = len(X)
for _ in range(epochs):
y_pred = w * X + b
dw = (2/n) * np.sum((y_pred - y) * X) # 计算梯度
db = (2/n) * np.sum(y_pred - y)
w -= lr * dw # 更新参数
b -= lr * db
return w, b
w, b = gradient_descent(X, y)
print(f"方程: y = {w:.2f}x + {b:.2f}")
# 可视化
plt.scatter(X, y, color='red')
plt.plot(X, w*X + b, label='预测线')
plt.legend()
plt.show()
思考:梯度下降中学习率过大/过小会发生什么?
级别2:多元线性回归(特征工程)
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
# 生成非线性数据
X = np.linspace(-3, 3, 100).reshape(-1,1)
y = 0.5*X**2 + X + 2 + np.random.randn(100,1)
# 使用多项式特征(二次项)
model = make_pipeline(
PolynomialFeatures(degree=2), # 添加二次特征
LinearRegression()
)
model.fit(X, y)
# 可视化拟合曲线
X_test = np.linspace(-3,3,100).reshape(-1,1)
plt.scatter(X, y, alpha=0.3)
plt.plot(X_test, model.predict(X_test), 'r', linewidth=2)
plt.title("二次多项式回归")
plt.show()
思考:如何避免多项式回归中的过拟合?
级别3:正则化回归(岭回归)
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
# 生成高维数据(20个特征,仅5个有用)
np.random.seed(42)
X = np.random.randn(100, 20)
y = X[:, 0] + 2*X[:, 1] - 1.5*X[:, 2] + 0.5*X[:, 3] + np.random.randn(100)
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 对比普通线性回归和岭回归
lin_reg = LinearRegression()
lin_reg.fit(X_scaled, y)
print("普通回归系数范围:", np.max(np.abs(lin_reg.coef_)))
ridge = Ridge(alpha=10) # 正则化强度
ridge.fit(X_scaled, y)
print("岭回归系数范围:", np.max(np.abs(ridge.coef_)))
输出:
普通回归系数范围: 5.23
岭回归系数范围: 1.87
思考:为什么高维数据需要正则化?如何选择alpha值?
二、逻辑回归
级别1:二分类(基础应用)
from sklearn.datasets import make_classification
# 生成可分数据
X, y = make_classification(n_features=2, n_redundant=0, n_clusters_per_class=1)
# 训练模型
model = LogisticRegression()
model.fit(X, y)
# 可视化决策边界
x_min, x_max = X[:,0].min()-1, X[:,0].max()+1
y_min, y_max = X[:,1].min()-1, X[:,1].max()+1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:,0], X[:,1], c=y, s=20)
plt.title("线性决策边界")
plt.show()
思考:为什么逻辑回归的决策边界是线性的?
级别2:多分类(鸢尾花数据集)
from sklearn.datasets import load_iris
# 加载数据
iris = load_iris()
X, y = iris.data[:, :2], iris.target # 只用前两个特征
# 使用One-vs-Rest策略
model = LogisticRegression(multi_class='ovr', max_iter=1000)
model.fit(X, y)
# 可视化多类决策边界
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:,0], X[:,1], c=y, edgecolor='k')
plt.xlabel("花萼长度")
plt.ylabel("花萼宽度")
plt.title("多分类决策边界")
plt.show()
思考:OvR(One-vs-Rest)和Softmax多分类的区别是什么?
级别3:类别不平衡处理(信用卡欺诈检测)
from sklearn.datasets import fetch_openml
from sklearn.metrics import precision_recall_curve
# 加载高度不平衡数据
data = fetch_openml('creditcardfraud')
X, y = data.data, data.target.astype(int)
# 重采样(SMOTE方法)
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_res, y_res = smote.fit_resample(X, y)
# 带权重调整的逻辑回归
model = LogisticRegression(class_weight='balanced', max_iter=1000)
model.fit(X_res, y_res)
# 绘制PR曲线
probs = model.predict_proba(X_res)[:,1]
precision, recall, _ = precision_recall_curve(y_res, probs)
plt.plot(recall, precision)
plt.xlabel("召回率")
plt.ylabel("精确率")
plt.title("类别不平衡下的PR曲线")
plt.show()
思考:为什么在处理欺诈检测时,精确率-召回率曲线比ROC曲线更有意义?
三、分类任务
级别1:KNN分类(原理理解)
from sklearn.neighbors import KNeighborsClassifier
# 生成同心圆数据
X, y = make_circles(n_samples=200, noise=0.1, factor=0.5)
# 不同K值对比
plt.figure(figsize=(12,4))
for i, k in enumerate([1, 10, 50]):
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X, y)
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.subplot(1,3,i+1)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:,0], X[:,1], c=y, s=20)
plt.title(f"K={k}")
plt.show()
思考:K值如何影响模型的偏差-方差权衡?
级别2:支持向量机(核技巧)
from sklearn.svm import SVC
# 生成螺旋数据
def generate_spiral():
theta = np.sqrt(np.random.rand(200))*2*np.pi
r = np.linspace(0, 1, 200)
X1 = np.array([r*np.cos(theta), r*np.sin(theta)]).T
X2 = np.array([-r*np.cos(theta), -r*np.sin(theta)]).T
return np.vstack((X1,X2)), np.hstack((np.zeros(200), np.ones(200)))
X, y = generate_spiral()
# 不同核函数对比
kernels = ['linear', 'rbf', 'poly']
plt.figure(figsize=(15,4))
for i, kernel in enumerate(kernels):
svm = SVC(kernel=kernel, gamma='auto')
svm.fit(X, y)
Z = svm.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.subplot(1,3,i+1)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:,0], X[:,1], c=y, s=20)
plt.title(f"{kernel} kernel")
plt.show()
思考:RBF核中的gamma参数控制什么?
级别3:集成方法(Stacking)
from sklearn.ensemble import StackingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
# 定义基模型和元模型
base_models = [
('dt', DecisionTreeClassifier(max_depth=3)),
('nb', GaussianNB()),
('svm', SVC(probability=True))
]
meta_model = LogisticRegression()
# 构建堆叠模型
stacking = StackingClassifier(
estimators=base_models,
final_estimator=meta_model,
stack_method='predict_proba'
)
# 在复杂数据集上测试
X, y = make_classification(n_samples=2000, n_features=20, n_informative=15)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
stacking.fit(X_train, y_train)
print(f"Stacking准确率: {stacking.score(X_test, y_test):.4f}")
print(f"对比单模型准确率:")
for name, model in base_models:
model.fit(X_train, y_train)
print(f"{name}: {model.score(X_test, y_test):.4f}")
输出示例:
Stacking准确率: 0.9233
对比单模型准确率:
dt: 0.8817
nb: 0.8567
svm: 0.8983
思考:为什么堆叠集成通常能提升性能?可能带来哪些缺点?
学习路径建议:
- 线性回归:从手工实现 → 理解多项式特征 → 掌握正则化
- 逻辑回归:从二分类基础 → 多分类扩展 → 处理实际数据问题
- 分类任务:从最近邻原理 → 理解核方法 → 掌握集成策略
我眼下日复一日的生活,将会成为我从未体察过的爱的记忆。 —费尔南多·佩索阿