机器学习算法部分demo
系列文章目录
文章目录
- 系列文章目录
- 一、RNN
- 1.1、核心特点
- 1.2、主要用处
- 二、CNN
- 2.1、核心特点
- 2.2、示例说明
- 2.3、运行后显示
- 2.4、主要用处
- 2.5、使用tensorflow测试
- 2.5.1、示例
- 三、其他机器学习算法
- 3.1、线性回归
- 3.2、逻辑回归
- 3.3、决策树(Decision Tree)
- 3.1、demo
- 3.4、随机森林(Random Forest)
- 3.4.1、 demo
- 3.5、支持向量机(SVM,Support Vector Machine)
- 3.6、K - 近邻(KNN,K-Nearest Neighbors)
- 3.7、聚类算法(如 K-Means)
- 3.8、朴素贝叶斯(Naive Bayes)
- 3.9、算法选择的核心依据
一、RNN
1.1、核心特点
处理序列数据: RNN最大的特点是引入时间维度,通过循环结构保留前序输入的信息,能够处理长度可变的序列数据,比如文件,语音,时间序列等
记忆性:网络中包含隐藏状态,用于存储历史信息,理论上能够捕捉长距离依赖关系
变种众多:解决原始RNN长期依赖(梯度消失/爆炸)问题的变种更常用
LSTM-长短期记忆网络:通过门控机制,输入门,遗忘门,输出门,选择性保留或者遗忘信息,适合长序列
GRU-门控循环单元:简化LSTM结构,计算效率高,性能接近LSTM
1.2、主要用处
自然语言处理NLP: 文本生成,机器翻译,情感分析,命名实体识别(比如北京是地名)
时间序列预测:股票价格预测,气象数据预测,设备故障预警
语音处理:语音识别,语音合成
二、CNN
2.1、核心特点
处理网络结构数据:专门为二维图像设计,扩展一维信号,三维视频,通过卷积操作提取局部特征,例如,图像中边缘纹理等局部特征是构成物体的基础,CNN能自动学习这些特征
权值共享与局部感受:
卷积核(过滤器)在图像上滑动时,参数共享,大幅减少计算量
每个神经元仅关注局部区域,符合视觉系统的局部感知特性
池化操作:通过下采样减少特征维度(如最大池化,平均池化),增强平移不变性(如猫的图像平移后仍能被识别)
2.2、示例说明
示例实现了MNIST手写数字识别(0-9的分类),核心部分包括:
-
数据准备:
- 使用MNIST数据集(28x28的灰度手写数字图像)
- 数据转换为张量并标准化
- 可视化展示了一些样本图像
-
CNN模型结构:
- 仅包含1个卷积层(提取图像局部特征)
- 1个池化层(降低特征图尺寸,保留关键信息)
- 1个全连接层(最终分类)
- 这是CNN的最基础结构,体现了"卷积-池化-分类"的核心流程
-
训练过程:
- 使用交叉熵损失函数(适合多分类任务)
- 使用Adam优化器更新参数
- 仅训练3轮,快速演示训练过程
-
模型评估:
- 在测试集上计算准确率(通常能达到97%以上)
- 可视化展示预测结果,对比预测值和实际标签
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np
from torchvision import datasets, transforms
from torch.utils.data import DataLoader# 设置随机种子,保证结果可复现
torch.manual_seed(42)
np.random.seed(42)# 1. 数据准备
# 定义数据转换:将图像转换为张量并标准化
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,)) # 标准化到[-1, 1]范围
])# 加载MNIST数据集(手写数字识别数据集)
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform
)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform
)# 创建数据加载器
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)# 可视化一些样本
def show_samples(dataset, num_samples=5):fig, axes = plt.subplots(1, num_samples, figsize=(10, 2))for i in range(num_samples):image, label = dataset[i]axes[i].imshow(image.squeeze().numpy(), cmap='gray')axes[i].set_title(f'标签: {label}')axes[i].axis('off')plt.show()print("样本图像:")
show_samples(train_dataset)# 2. 定义最简单的CNN模型
class SimpleCNN(nn.Module):def __init__(self):super().__init__()# 卷积层:输入1个通道(灰度图),输出16个特征图,卷积核大小3x3self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)# 池化层:2x2最大池化self.pool = nn.MaxPool2d(kernel_size=2, stride=2)# 全连接层:将特征映射到10个类别(0-9)self.fc = nn.Linear(16 * 14 * 14, 10) # 14x14是池化后的尺寸def forward(self, x):# 卷积 -> ReLU激活 -> 池化x = self.pool(torch.relu(self.conv1(x)))# 展平特征图x = x.view(-1, 16 * 14 * 14)# 全连接层输出x = self.fc(x)return x# 初始化模型、损失函数和优化器
model = SimpleCNN()
criterion = nn.CrossEntropyLoss() # 交叉熵损失,适用于分类
optimizer = optim.Adam(model.parameters(), lr=0.001)# 3. 训练模型
epochs = 3 # 只训练3轮,简单演示
train_losses = []for epoch in range(epochs):model.train()running_loss = 0.0for images, labels in train_loader:# 前向传播outputs = model(images)loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()running_loss += loss.item()# 计算平均损失avg_loss = running_loss / len(train_loader)train_losses.append(avg_loss)print(f'Epoch {epoch + 1}/{epochs}, 训练损失: {avg_loss:.4f}')# 绘制训练损失曲线
plt.plot(range(1, epochs + 1), train_losses)
plt.xlabel('Epoch')
plt.ylabel('损失')
plt.title('训练损失变化')
plt.show()# 4. 评估模型
model.eval()
correct = 0
total = 0with torch.no_grad(): # 关闭梯度计算for images, labels in test_loader:outputs = model(images)_, predicted = torch.max(outputs.data, 1) # 获取预测类别total += labels.size(0)correct += (predicted == labels).sum().item()print(f'测试集准确率: {100 * correct / total:.2f}%')# 5. 可视化预测结果
def show_predictions(loader, model, num_samples=5):model.eval()images, labels = next(iter(loader))with torch.no_grad():outputs = model(images)_, predicted = torch.max(outputs, 1)fig, axes = plt.subplots(1, num_samples, figsize=(10, 2))for i in range(num_samples):axes[i].imshow(images[i].squeeze().numpy(), cmap='gray')axes[i].set_title(f'预测: {predicted[i]}, 实际: {labels[i]}')axes[i].axis('off')plt.show()print("预测结果示例:")
show_predictions(test_loader, model)
2.3、运行后显示
- 5个样本图像及其标签
- 训练过程中的损失变化曲线
- 模型在测试集上的准确率
- 5个测试样本的预测结果
CNN的核心思想:通过卷积操作提取图像的局部特征(如边缘、纹理等),通过池化减少特征维度,最后通过全连接层完成分类。你可以尝试增加卷积层数量或调整卷积核大小,观察对模型性能的影响。
2.4、主要用处
计算机视觉: 图像分类(比如识别猫狗),目标检测(如检测照片中的行人,车辆),图像分割(比如医学影像中分割肿瘤区域),人脸识别
其他领域: 一维CNN可以处理音频信号,二维CNN可以处理雷达数据,三维CNN可以处理视频帧序列
2.5、使用tensorflow测试
PyTorch 和Tensorflow都是功能相近的深度学习框架,提供了从数据处理,模型搭建,训练到部署的全流程支持,都能实现开箱即用的体验,都提供了
张量计算:类似于GPU加速的NumPy
自动微分:自动计算梯度,无需手动推导
丰富的神经网络层
优化器和损失函数
数据加载和预处理工具
下面为你提供一个使用TensorFlow/Keras实现的CNN(卷积神经网络)简单示例,用于MNIST手写数字识别任务。代码简洁且包含详细注释,适合入门学习。
2.5.1、示例
TensorFlow/Keras实现了一个简单的CNN,用于MNIST手写数字识别(0-9分类),主要包含以下部分:
-
数据处理:
- 加载MNIST数据集(28x28像素的灰度手写数字图像)
- 数据归一化(将像素值从0-255转换为0-1)
- 增加通道维度(CNN需要[高度, 宽度, 通道数]格式的输入,灰度图通道数为1)
-
CNN模型结构:
- 1个卷积层(32个3x3卷积核):负责提取图像局部特征(如边缘、线条)
- 1个池化层(2x2最大池化):降低特征图尺寸,保留关键信息,减少计算量
- 1个展平层:将二维特征图转换为一维向量
- 1个全连接层(10个输出):通过softmax激活函数输出0-9的分类概率
-
模型训练与评估:
- 使用Adam优化器和交叉熵损失函数
- 训练3轮(快速演示),使用64的批次大小
- 自动划分10%的训练数据作为验证集,监控过拟合情况
- 在测试集上评估最终性能(通常准确率可达98%以上)
-
可视化:
- 展示样本图像及其标签
- 绘制训练过程中的损失和准确率变化曲线
- 展示测试样本的预测结果与实际标签对比
5. 运行后会自动下载MNIST数据集(首次运行)
- 5个训练样本的图像及标签
- 模型结构摘要
- 训练过程中的损失和准确率变化曲线
- 测试集上的最终准确率
- 5个测试样本的预测结果
# _*_coding : utf-8 _*_
# @Time : 2025/10/6 23:32
# @Author : Leo
# @File : tensorflow_test
# @Project : nn
import tensorflow as tf
from tensorflow.keras import layers, models
import matplotlib.pyplot as plt
import numpy as np# 设置随机种子,保证结果可复现
tf.random.set_seed(42)
np.random.seed(42)# 1. 加载并预处理数据
# 加载MNIST数据集(手写数字识别数据集)
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()# 数据预处理:归一化并增加通道维度(灰度图通道数为1)
x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0
x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0# 可视化一些样本
plt.figure(figsize=(10, 2))
for i in range(5):plt.subplot(1, 5, i + 1)plt.imshow(x_train[i].squeeze(), cmap='gray')plt.title(f'标签: {y_train[i]}')plt.axis('off')
plt.show()# 2. 构建最简单的CNN模型
model = models.Sequential([# 第一个卷积层:32个3x3卷积核,ReLU激活layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),# 池化层:2x2最大池化layers.MaxPooling2D((2, 2)),# 展平层:将多维特征转为一维layers.Flatten(),# 全连接层:10个输出(对应0-9数字)layers.Dense(10, activation='softmax')
])# 打印模型结构
model.summary()# 3. 编译模型
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy', # 适用于整数标签的多分类metrics=['accuracy']
)# 4. 训练模型
history = model.fit(x_train, y_train,epochs=3, # 简单演示,训练3轮batch_size=64,validation_split=0.1 # 用10%的训练数据作为验证集
)# 绘制训练曲线
plt.figure(figsize=(12, 4))# 损失曲线
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='训练损失')
plt.plot(history.history['val_loss'], label='验证损失')
plt.xlabel('Epoch')
plt.ylabel('损失')
plt.legend()
plt.title('损失变化')# 准确率曲线
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='训练准确率')
plt.plot(history.history['val_accuracy'], label='验证准确率')
plt.xlabel('Epoch')
plt.ylabel('准确率')
plt.legend()
plt.title('准确率变化')plt.tight_layout()
plt.show()# 5. 在测试集上评估模型
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'\n测试集准确率: {test_acc:.4f}')# 6. 可视化预测结果
predictions = model.predict(x_test)plt.figure(figsize=(10, 2))
for i in range(5):plt.subplot(1, 5, i + 1)plt.imshow(x_test[i].squeeze(), cmap='gray')predicted_label = np.argmax(predictions[i])actual_label = y_test[i]plt.title(f'预测: {predicted_label}\n实际: {actual_label}')plt.axis('off')
plt.tight_layout()
plt.show()
三、其他机器学习算法
3.1、线性回归
特点:最简单的监督学习算法,假设特征与目标值呈线性关系,通过拟合直线(高维空间为超平面)预测连续值
用处:房价预测,销售额预测,气温预测等回归任务
# _*_coding : utf-8 _*_
# @Time : 2025/10/6 20:26
# @Author : Leo
# @File : linear_test
# @Project : nn
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np# 设置随机种子,保证结果可复现
torch.manual_seed(42)
np.random.seed(42)# 1. 生成模拟数据
# 假设我们的数据符合 y = 3x + 2 + 噪声 这个线性关系
x = torch.linspace(0, 10, 100).unsqueeze(1) # 生成0到10之间的100个点,形状为(100, 1)
noise = torch.randn(100, 1) * 0.5 # 生成噪声
y = 3 * x + 2 + noise # 生成目标值# 可视化生成的数据
plt.scatter(x.numpy(), y.numpy(), label='数据点')
plt.xlabel('x')
plt.ylabel('y')
plt.title('模拟数据')
plt.legend()
plt.show()# 2. 定义线性回归模型
class LinearRegressionModel(nn.Module):def __init__(self):super().__init__()# 定义一个线性层:输入维度1,输出维度1self.linear = nn.Linear(in_features=1, out_features=1)def forward(self, x):# 前向传播:直接通过线性层计算return self.linear(x)# 初始化模型
model = LinearRegressionModel()# 3. 定义损失函数和优化器
criterion = nn.MSELoss() # 均方误差损失,适用于回归问题
optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降优化器,学习率0.01# 4. 训练模型
epochs = 1000 # 训练轮次
losses = [] # 记录损失变化for epoch in range(epochs):# 前向传播:计算模型预测值y_pred = model(x)# 计算损失loss = criterion(y_pred, y)losses.append(loss.item())# 反向传播和参数更新optimizer.zero_grad() # 清零梯度loss.backward() # 计算梯度optimizer.step() # 更新参数# 每100轮打印一次损失if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}')# 5. 可视化损失变化
plt.plot(range(epochs), losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('训练损失变化')
plt.show()# 6. 查看训练得到的参数
# 原始公式是 y = 3x + 2,看看我们学到的参数是否接近
print("\n训练得到的参数:")
for name, param in model.named_parameters():print(f"{name}: {param.item():.4f}")# 7. 用训练好的模型进行预测并可视化
y_pred = model(x)plt.scatter(x.numpy(), y.numpy(), label='原始数据')
plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', label='拟合直线')
plt.xlabel('x')
plt.ylabel('y')
plt.title('线性回归拟合结果')
plt.legend()
plt.show()# 8. 使用模型进行新的预测
new_x = torch.tensor([[5.5], [7.2], [9.8]]) # 新的输入数据
new_y_pred = model(new_x) # 预测结果print("\n新数据的预测结果:")
for i in range(len(new_x)):print(f"x = {new_x[i].item()}, 预测y = {new_y_pred[i].item():.4f}")
3.2、逻辑回归
特点:属于分类算法,通过sigmoid函数将线性输出映射到[0,1]区间,用于二分类(如”是/否“, ”垃圾邮件/正常邮件“)
用处:信用评分,疾病诊断,点击率预测
运行后会显示:
原始数据集的散点图
训练和测试损失随迭代的变化曲线
模型在训练集和测试集上的准确率
逻辑回归的决策边界可视化import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split# 设置随机种子,保证结果可复现
torch.manual_seed(42)
np.random.seed(42)# 1. 生成模拟的二分类数据
# 生成100个样本,2个特征,2个类别
X, y = make_classification(n_samples=100, # 样本数量n_features=2, # 特征数量n_informative=2, # 有效特征数量n_redundant=0, # 冗余特征数量n_classes=2, # 类别数量random_state=42
)# 转换为PyTorch张量
X = torch.tensor(X, dtype=torch.float32)
y = torch.tensor(y, dtype=torch.float32).unsqueeze(1) # 增加一个维度,使其形状为(100, 1)# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42
)# 可视化生成的数据
plt.scatter(X[y[:, 0] == 0, 0], X[y[:, 0] == 0, 1], label='类别 0', marker='o')
plt.scatter(X[y[:, 0] == 1, 0], X[y[:, 0] == 1, 1], label='类别 1', marker='x')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('二分类数据集')
plt.legend()
plt.show()# 2. 定义逻辑回归模型
class LogisticRegressionModel(nn.Module):def __init__(self, input_dim):super().__init__()# 线性层:输入维度为特征数,输出维度为1(二分类)self.linear = nn.Linear(input_dim, 1)# 逻辑回归的sigmoid激活函数会在计算损失时一起使用def forward(self, x):# 前向传播:线性变换 + sigmoid激活return torch.sigmoid(self.linear(x))# 初始化模型(输入维度为2,因为我们有2个特征)
model = LogisticRegressionModel(input_dim=2)# 3. 定义损失函数和优化器
criterion = nn.BCELoss() # 二元交叉熵损失,适用于二分类问题
optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降优化器# 4. 训练模型
epochs = 10000 # 训练轮次
train_losses = []
test_losses = []for epoch in range(epochs):# 训练模式model.train()# 前向传播:计算训练集预测值y_pred_train = model(X_train)# 计算训练损失train_loss = criterion(y_pred_train, y_train)train_losses.append(train_loss.item())# 反向传播和参数更新optimizer.zero_grad() # 清零梯度train_loss.backward() # 计算梯度optimizer.step() # 更新参数# 评估模式model.eval()with torch.no_grad(): # 关闭梯度计算y_pred_test = model(X_test)test_loss = criterion(y_pred_test, y_test)test_losses.append(test_loss.item())# 每1000轮打印一次损失if (epoch + 1) % 1000 == 0:print(f'Epoch [{epoch + 1}/{epochs}], 训练损失: {train_loss.item():.4f}, 测试损失: {test_loss.item():.4f}')# 5. 可视化损失变化
plt.plot(range(epochs), train_losses, label='训练损失')
plt.plot(range(epochs), test_losses, label='测试损失')
plt.xlabel('Epoch')
plt.ylabel('损失')
plt.title('训练和测试损失变化')
plt.legend()
plt.show()# 6. 评估模型准确率
model.eval()
with torch.no_grad():# 训练集准确率y_pred_train = model(X_train)y_pred_train_class = (y_pred_train > 0.5).float() # 大于0.5预测为1,否则为0train_acc = (y_pred_train_class == y_train).float().mean()# 测试集准确率y_pred_test = model(X_test)y_pred_test_class = (y_pred_test > 0.5).float()test_acc = (y_pred_test_class == y_test).float().mean()print(f'\n训练集准确率: {train_acc.item():.4f}')
print(f'测试集准确率: {test_acc.item():.4f}')# 7. 可视化决策边界
# 生成网格点用于绘制决策边界
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))# 预测网格点的类别
with torch.no_grad():inputs = torch.tensor(np.c_[xx.ravel(), yy.ravel()], dtype=torch.float32)outputs = model(inputs)predicted = (outputs > 0.5).float()Z = predicted.reshape(xx.shape)# 绘制决策边界和数据点
plt.contourf(xx, yy, Z, alpha=0.4, cmap=plt.cm.RdBu)
plt.scatter(X[y[:, 0] == 0, 0], X[y[:, 0] == 0, 1], label='类别 0', marker='o', c='blue')
plt.scatter(X[y[:, 0] == 1, 0], X[y[:, 0] == 1, 1], label='类别 1', marker='x', c='red')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('逻辑回归决策边界')
plt.legend()
plt.show()
3.3、决策树(Decision Tree)
特点:模拟人类决策过程,通过对特征的 “提问”(如 “年龄是否 > 30?”)逐步划分数据,最终得到分类或回归结果。可解释性强(类似 “流程图”)。
用处:客户流失分析、风险评估、医疗诊断(直观展示决策依据)。
3.1、demo
这个决策树示例使用鸢尾花数据集实现了一个多分类任务,主要包含以下几个部分:
-
数据准备:
- 使用scikit-learn内置的鸢尾花数据集,包含3种鸢尾花的特征数据
- 为了便于可视化,仅使用了前两个特征(花萼长度和花萼宽度)
- 将数据集划分为训练集(70%)和测试集(30%)
-
模型训练:
- 使用
DecisionTreeClassifier
创建决策树分类器 - 通过
max_depth=3
限制决策树深度,避免过拟合 - 使用训练集训练模型
- 使用
-
模型评估:
- 在测试集上进行预测并计算准确率
- 生成详细的分类报告,包括精确率、召回率和F1分数
-
可视化:
- 展示原始数据集的分布情况
- 可视化决策树的结构,清晰展示每个节点的分裂条件和类别判断
- 绘制决策边界,直观展示模型如何对特征空间进行划分
-
运行后显示:
- 鸢尾花数据集的散点图
- 模型的准确率和详细分类报告
- 决策树的结构可视化
- 决策边界的可视化
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, classification_report# 1. 加载数据集(使用经典的鸢尾花数据集)
iris = load_iris()
X = iris.data[:, :2] # 仅使用前两个特征,方便可视化
y = iris.target# 数据集信息
print(f"特征名称: {iris.feature_names[:2]}")
print(f"类别名称: {iris.target_names}")
print(f"数据集大小: {X.shape[0]}个样本, {X.shape[1]}个特征")# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42
)# 可视化数据集
plt.figure(figsize=(8, 6))
colors = ['red', 'green', 'blue']
for i in range(3):plt.scatter(X[y == i, 0], X[y == i, 1],c=colors[i], label=iris.target_names[i])
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])
plt.title('鸢尾花数据集可视化')
plt.legend()
plt.show()# 2. 创建并训练决策树模型
# 初始化决策树分类器,限制最大深度为3,避免过拟合
clf = DecisionTreeClassifier(max_depth=3, random_state=42)
clf.fit(X_train, y_train)# 3. 模型预测与评估
# 在测试集上进行预测
y_pred = clf.predict(X_test)# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"\n模型准确率: {accuracy:.4f}")# 详细分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))# 4. 可视化决策树
plt.figure(figsize=(12, 8))
plot_tree(clf,feature_names=iris.feature_names[:2],class_names=iris.target_names,filled=True, # 填充颜色rounded=True, # 圆角矩形proportion=True # 显示每个节点中各类别的比例
)
plt.title('决策树结构可视化')
plt.show()# 5. 可视化决策边界
# 创建网格用于绘制决策边界
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 = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)# 绘制决策边界和数据点
plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.coolwarm)
for i in range(3):plt.scatter(X[y == i, 0], X[y == i, 1],c=colors[i], label=iris.target_names[i])
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])
plt.title('决策树决策边界')
plt.legend()
plt.show()
3.4、随机森林(Random Forest)
特点:由多个决策树组成的集成算法,通过 “bootstrap 抽样” 和 “随机特征选择” 减少过拟合,预测精度高于单棵决策树。
用处: Kaggle 竞赛常用模型,适用于分类(如疾病风险分类)和回归(如房价预测),也可用于特征重要性评估。
3.4.1、 demo
使用月牙形数据集实现了二分类任务
-
数据准备:
- 使用
make_moons
生成非线性可分的月牙形数据集,更能体现随机森林处理复杂模式的能力 - 将数据集划分为训练集(70%)和测试集(30%)
- 可视化展示数据集分布
- 使用
-
模型训练:
- 使用
RandomForestClassifier
创建随机森林分类器 - 核心参数:
n_estimators=100
(由100棵决策树组成)、max_depth=5
(控制单棵树复杂度) - 随机森林通过集成多棵决策树的预测结果(多数投票)来提高性能
- 使用
-
模型评估:
- 计算模型在测试集上的准确率
- 生成详细分类报告(精确率、召回率、F1分数)
- 可视化混淆矩阵,展示分类错误情况
-
特征重要性:
- 随机森林可以自动计算并输出特征重要性得分
- 帮助理解哪些特征对分类决策贡献更大
-
决策边界可视化:
- 展示随机森林学习到的决策边界
- 可以看到随机森林能处理非线性边界,比单棵决策树更稳健
-
运行后会显示:
- 月牙形数据集的分布散点图
- 模型准确率和详细分类报告
- 混淆矩阵热图
- 特征重要性柱状图
- 随机森林的决策边界可视化
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import seaborn as sns# 1. 生成模拟数据集(月牙形数据集,更适合展示随机森林的优势)
X, y = make_moons(n_samples=300, noise=0.2, random_state=42)# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42
)# 可视化数据集
plt.figure(figsize=(8, 6))
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='blue', label='类别 0', alpha=0.7)
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='red', label='类别 1', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('模拟月牙形数据集')
plt.legend()
plt.show()# 2. 创建并训练随机森林模型
# 初始化随机森林分类器
# n_estimators: 森林中树的数量
# max_depth: 每棵树的最大深度,控制复杂度
rf = RandomForestClassifier(n_estimators=100, # 100棵决策树max_depth=5, # 每棵树最大深度为5random_state=42 # 随机种子,保证结果可复现
)# 训练模型
rf.fit(X_train, y_train)# 3. 模型预测与评估
# 在测试集上进行预测
y_pred = rf.predict(X_test)
y_pred_proba = rf.predict_proba(X_test) # 预测概率# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.4f}")# 详细分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred))# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(6, 4))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',xticklabels=['类别 0', '类别 1'],yticklabels=['类别 0', '类别 1'])
plt.xlabel('预测类别')
plt.ylabel('实际类别')
plt.title('混淆矩阵')
plt.show()# 4. 可视化特征重要性
feature_importance = rf.feature_importances_
plt.figure(figsize=(6, 4))
plt.bar(['特征 1', '特征 2'], feature_importance)
plt.ylabel('重要性得分')
plt.title('随机森林特征重要性')
plt.show()# 5. 可视化决策边界
# 创建网格用于绘制决策边界
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),np.arange(y_min, y_max, 0.02))# 预测网格点的类别
Z = rf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)# 绘制决策边界和数据点
plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.coolwarm)
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='blue', label='类别 0', alpha=0.7)
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='red', label='类别 1', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('随机森林决策边界')
plt.legend()
plt.show()
随机森林是一种集成学习算法,通过组合多棵决策树的预测结果来提高性能和稳定性,同时减少过拟合风险。你可以尝试修改n_estimators
(树的数量)和max_depth
(树的深度)等参数,观察对模型性能的影响。一般来说,增加树的数量可以提高性能(但会增加计算成本),适当限制树的深度可以防止过拟合。
3.5、支持向量机(SVM,Support Vector Machine)
特点:寻找 “最优超平面” 最大化分类间隔,通过核函数(如 RBF 核)处理非线性数据,在小样本场景表现优异。
用处:文本分类、图像识别(早期)、生物信息学(如蛋白质分类)。
3.6、K - 近邻(KNN,K-Nearest Neighbors)
特点:无训练过程的 “惰性学习” 算法,通过计算新样本与训练样本的距离(如欧氏距离),取最近的 K 个样本的多数类别作为预测结果。
用处:推荐系统(如 “相似用户喜欢的商品”)、手写数字识别、异常检测。
3.7、聚类算法(如 K-Means)
特点:无监督学习算法,将相似样本自动归为一类,无需标签数据。K-Means 通过迭代优化聚类中心实现分类。
用处:用户分群(如电商用户画像聚类)、异常检测(远离聚类中心的样本)、图像分割(像素聚类)。
3.8、朴素贝叶斯(Naive Bayes)
特点:基于贝叶斯定理和 “特征条件独立假设” 的分类算法,计算高效,适合高维数据(如文本)。
用处:垃圾邮件过滤(词袋模型 + 贝叶斯)、文本分类(如新闻主题分类)、情感分析。
3.9、算法选择的核心依据
数据类型:
序列数据(文本、语音、时间序列)→ RNN/LSTM/GRU;
网格数据(图像、视频)→ CNN;
结构化数据(表格数据)→ 决策树、随机森林、逻辑回归等。
任务类型:
分类(离散标签)→ 逻辑回归、SVM、随机森林、CNN/RNN;
回归(连续值)→ 线性回归、决策树、随机森林;
无监督学习(无标签)→ 聚类算法、PCA(降维)。
数据规模:
小样本 → SVM、朴素贝叶斯;
大样本 → 深度学习(CNN/RNN)、随机森林。