神经网络解决非线性二分类

这份 Python 代码实现了一个简单的神经网络,用于解决复杂的非线性二分类问题。具体步骤包含生成数据集、定义神经网络模型、训练模型、测试模型以及可视化决策边界。

依赖库说明

python

复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
  • numpy:用于数值计算,如数组操作、矩阵运算等。
  • matplotlib.pyplot:用于数据可视化,如绘制决策边界和数据点。
  • make_moons:从sklearn.datasets导入,用于生成半月形的非线性分类数据集。
  • train_test_split:从sklearn.model_selection导入,用于将数据集划分为训练集和测试集。

详细步骤说明

1. 生成复杂的非线性分类数据集

python

复制代码
np.random.seed(42)
X, y = make_moons(n_samples=1000, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
  • np.random.seed(42):设置随机数种子,保证结果可复现。
  • make_moons(n_samples=1000, noise=0.2, random_state=42):生成包含 1000 个样本的半月形数据集,噪声水平为 0.2。
  • train_test_split(X, y, test_size=0.2, random_state=42):将数据集按 80:20 的比例划分为训练集和测试集。
2. 定义神经网络(带隐藏层的非线性分类模型)

python

复制代码
class SimpleNN:
    def __init__(self, input_size=2, hidden_size=10, output_size=1):
        self.w1 = np.random.randn(input_size, hidden_size)
        self.b1 = np.random.randn(hidden_size)
        self.w2 = np.random.randn(hidden_size, output_size)
        self.b2 = np.random.randn(output_size)
  • __init__方法:初始化神经网络的权重和偏置。input_size为输入层神经元数量,hidden_size为隐藏层神经元数量,output_size为输出层神经元数量。

python

复制代码
    def sigmoid(self, x):
        return 1 / (1 + np.exp(-x))

    def relu(self, x):
        return np.maximum(0, x)
  • sigmoid方法:实现 Sigmoid 激活函数,将输入值映射到 (0, 1) 区间,常用于二分类问题的输出层。
  • relu方法:实现 ReLU 激活函数,将小于 0 的值置为 0,大于等于 0 的值保持不变,可缓解梯度消失问题。

python

复制代码
    def forward(self, x):
        self.z1 = np.dot(x, self.w1) + self.b1
        self.a1 = self.relu(self.z1)
        self.z2 = np.dot(self.a1, self.w2) + self.b2
        self.a2 = self.sigmoid(self.z2)
        return self.a2
  • forward方法:实现神经网络的前向传播过程。输入数据经过输入层到隐藏层的线性变换,再通过 ReLU 激活函数;然后经过隐藏层到输出层的线性变换,最后通过 Sigmoid 激活函数得到输出。

python

复制代码
    def binary_cross_entropy(self, y_true, y_pred):
        return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
  • binary_cross_entropy方法:计算二分类交叉熵损失,衡量模型预测值与真实值之间的差异。

python

复制代码
    def gradient(self, x, y_true, y_pred):
        m = x.shape[0]
        d_z2 = y_pred - y_true
        d_w2 = np.dot(self.a1.T, d_z2) / m
        d_b2 = np.sum(d_z2, axis=0) / m
        d_a1 = np.dot(d_z2, self.w2.T)
        d_z1 = d_a1 * (self.z1 > 0)
        d_w1 = np.dot(x.T, d_z1) / m
        d_b1 = np.sum(d_z1, axis=0) / m
        return d_w1, d_b1, d_w2, d_b2
  • gradient方法:实现反向传播算法,计算权重和偏置的梯度。

python

复制代码
    def train(self, x, y, lr=0.01, epochs=1000):
        for epoch in range(epochs):
            y_pred = self.forward(x)
            dw1, db1, dw2, db2 = self.gradient(x, y, y_pred)
            self.w1 -= lr * dw1
            self.b1 -= lr * db1
            self.w2 -= lr * dw2
            self.b2 -= lr * db2
            if (epoch + 1) % 100 == 0:
                loss = self.binary_cross_entropy(y, y_pred)
                acc = self.accuracy(y, y_pred)
                print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss:.4f}, Accuracy: {acc:.4f}')
  • train方法:训练神经网络。在每个 epoch 中,先进行前向传播得到预测值,再通过反向传播计算梯度,最后更新权重和偏置。每 100 个 epoch 打印一次损失和准确率。

python

复制代码
    def accuracy(self, y_true, y_pred):
        y_pred_class = (y_pred > 0.5).astype(int)
        return np.mean(y_pred_class == y_true)
  • accuracy方法:计算分类准确率,将预测概率大于 0.5 的样本判定为正类,小于等于 0.5 的判定为负类,然后计算预测正确的样本比例。
3. 训练模型

python

复制代码
model = SimpleNN(input_size=2, hidden_size=10, output_size=1)
model.train(X_train, y_train.reshape(-1, 1), lr=0.01, epochs=2000)
  • 创建SimpleNN类的实例model,并调用train方法对模型进行训练,学习率为 0.01,训练 2000 个 epoch。
4. 测试模型

python

复制代码
y_test_pred = model.forward(X_test)
test_acc = model.accuracy(y_test.reshape(-1, 1), y_test_pred)
print(f'Test Accuracy: {test_acc:.4f}')
  • 使用训练好的模型对测试集进行预测,计算测试集的准确率并打印。
5. 可视化决策边界

python

复制代码
def plot_decision_boundary(model, 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.01),
                         np.arange(y_min, y_max, 0.01))
    grid = np.c_[xx.ravel(), yy.ravel()]
    probs = model.forward(grid).reshape(xx.shape)
    plt.contourf(xx, yy, probs, levels=[0, 0.5, 1], alpha=0.8, cmap=plt.cm.RdBu)
    plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', cmap=plt.cm.RdBu)
    plt.title("Decision Boundary")
    plt.show()

plot_decision_boundary(model, X_test, y_test)
  • plot_decision_boundary函数:绘制模型的决策边界。首先创建一个网格,然后对网格中的每个点进行预测,最后使用contourf函数绘制决策区域,并使用scatter函数绘制数据点。
  • 调用plot_decision_boundary函数,传入训练好的模型、测试集数据和标签,可视化决策边界。

总结

该代码实现了一个简单的两层神经网络,用于解决复杂的非线性二分类问题。通过生成数据集、定义模型、训练模型、测试模型和可视化决策边界等步骤,展示了神经网络在非线性分类任务中的应用。

完整代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split

# 1. 生成复杂的非线性分类数据集
np.random.seed(42)
X, y = make_moons(n_samples=1000, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. 定义神经网络(带隐藏层的非线性分类模型)
class SimpleNN:
    def __init__(self, input_size=2, hidden_size=10, output_size=1):
        # 初始化权重和偏置
        self.w1 = np.random.randn(input_size, hidden_size)  # 输入层到隐藏层的权重
        self.b1 = np.random.randn(hidden_size)              # 隐藏层的偏置
        self.w2 = np.random.randn(hidden_size, output_size)  # 隐藏层到输出层的权重
        self.b2 = np.random.randn(output_size)              # 输出层的偏置

    def sigmoid(self, x):
        return 1 / (1 + np.exp(-x))  # Sigmoid激活函数

    def relu(self, x):
        return np.maximum(0, x)  # ReLU激活函数

    def forward(self, x):
        # 前向传播
        self.z1 = np.dot(x, self.w1) + self.b1  # 隐藏层输入
        self.a1 = self.relu(self.z1)            # 隐藏层输出(应用ReLU)
        self.z2 = np.dot(self.a1, self.w2) + self.b2  # 输出层输入
        self.a2 = self.sigmoid(self.z2)         # 输出层输出(应用Sigmoid)
        return self.a2

    def binary_cross_entropy(self, y_true, y_pred):
        # 二分类交叉熵损失
        return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))

    def gradient(self, x, y_true, y_pred):
        # 反向传播计算梯度
        m = x.shape[0]
        # 输出层的梯度
        d_z2 = y_pred - y_true
        d_w2 = np.dot(self.a1.T, d_z2) / m
        d_b2 = np.sum(d_z2, axis=0) / m
        # 隐藏层的梯度
        d_a1 = np.dot(d_z2, self.w2.T)
        d_z1 = d_a1 * (self.z1 > 0)  # ReLU的导数
        d_w1 = np.dot(x.T, d_z1) / m
        d_b1 = np.sum(d_z1, axis=0) / m
        return d_w1, d_b1, d_w2, d_b2

    def train(self, x, y, lr=0.01, epochs=2000):
        for epoch in range(epochs):
            y_pred = self.forward(x)
            dw1, db1, dw2, db2 = self.gradient(x, y, y_pred)
            # 更新权重和偏置
            self.w1 -= lr * dw1
            self.b1 -= lr * db1
            self.w2 -= lr * dw2
            self.b2 -= lr * db2
            if (epoch + 1) % 100 == 0:
                loss = self.binary_cross_entropy(y, y_pred)
                acc = self.accuracy(y, y_pred)
                print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss:.4f}, Accuracy: {acc:.4f}')

    def accuracy(self, y_true, y_pred):
        # 计算分类准确率
        y_pred_class = (y_pred > 0.5).astype(int)
        return np.mean(y_pred_class == y_true)

# 3. 训练模型
model = SimpleNN(input_size=2, hidden_size=10, output_size=1)
model.train(X_train, y_train.reshape(-1, 1), lr=0.01, epochs=2000)

# 4. 测试模型
y_test_pred = model.forward(X_test)
test_acc = model.accuracy(y_test.reshape(-1, 1), y_test_pred)
print(f'Test Accuracy: {test_acc:.4f}')

# 5. 可视化决策边界
def plot_decision_boundary(model, 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.01),
                         np.arange(y_min, y_max, 0.01))
    grid = np.c_[xx.ravel(), yy.ravel()]
    probs = model.forward(grid).reshape(xx.shape)
    plt.contourf(xx, yy, probs, levels=[0, 0.5, 1], alpha=0.8, cmap=plt.cm.RdBu)
    plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', cmap=plt.cm.RdBu)
    plt.title("Decision Boundary")
    plt.show()

plot_decision_boundary(model, X_test, y_test)
相关推荐
2301_7644413316 分钟前
基于BERT的序列到序列(Seq2Seq)模型,生成文本摘要或标题
人工智能·python·深度学习·bert
说私域27 分钟前
开源链动2+1模式与AI智能名片赋能的S2B2C共享经济新生态
人工智能·微信·小程序·开源
蹦蹦跳跳真可爱5891 小时前
Python----计算机视觉处理(Opencv:霍夫变换)
人工智能·python·opencv·计算机视觉
Angel Q.1 小时前
3D点云的深度学习网络分类(按照作用分类)
深度学习·3d·分类
livefan1 小时前
英伟达「虚拟轨道+AI调度」专利:开启自动驾驶3.0时代的隐形革命
人工智能·机器学习·自动驾驶
wd2099881 小时前
手绘的思维导图怎么转成电子版思维导图?分享今年刚测试出来的方法
人工智能·powerpoint
魔珐科技1 小时前
专访中兴通讯蒋军:AI数字人驱动企业培训,“内容生产”与“用户体验”双重提升
人工智能·aigc·ai数字人
果冻人工智能1 小时前
Linux 之父把 AI 泡沫喷了个遍:90% 是营销,10% 是现实。
人工智能
果冻人工智能2 小时前
Sal Khan 和 Bill Gates 对 AI 的看法错了
人工智能