Python神经网络编程(一):预测器、分类器与神经网络基础概念
Python神经网络编程(一):预测器、分类器与神经网络基础概念
本文是《Python神经网络编程》系列博客的第1篇,基于真实服务器实操输出,涵盖实验1-2的所有内容。
服务器环境:Ubuntu 24.04 / Python 3.12.3 / NumPy 2.5.1 / Matplotlib 3.11.0
服务器:华为云 ecs-1f62-0001 (120.46.93.164)
目录
你将学到什么
在本篇博客中,你将通过从零开始的数学推导和Python代码实操,理解神经网络的核心概念:
- 预测器(Predictor):线性回归如何工作
- 分类器(Classifier):从回归到分类的跨越
- 线性分类器的局限性:为什么XOR问题无法用一条直线解决
- 激活函数(Activation Function):给神经网络引入非线性
- 神经网络的结构:从单层到多层,从线性到非线性
实验1:预测器与分类器
1.1 人工智能的概念
人工智能(Artificial Intelligence, AI) 的本质是让机器能够模拟人类的智能行为,包括学习、推理、感知和决策。
神经网络是人工智能的一个重要分支,它受到生物神经网络的启发:
生物神经网络 人工神经网络
┌──────────┐ ┌──────────┐
│ 神经元 │ │ 节点 │
│ (Neuron) │ ←类比→ │ (Node) │
└──────────┘ └──────────┘
│ │
▼ ▼
树突接收信号 加权求和 + 激活函数
轴突传递信号 输出到下一层
1.2 预测机(Predictor)
预测器是一个简单的数学模型,用于根据输入预测输出。
核心公式
y = w × x + b
其中:
x:输入(特征)y:输出(预测值)w:权重(weight),表示输入对输出的影响程度b:偏置(bias),表示当输入为0时的输出
Python实现:简单线性预测器
import numpy as np
# 简单线性预测器
def predict(x, w, b):
"""简单的线性预测器"""
return w * x + b
# 示例:根据学习时间预测考试分数
# 训练数据:(学习时间, 考试分数)
training_data = [
[1.0, 35.0],
[2.0, 48.0],
[3.0, 62.0],
[4.0, 75.0],
[5.0, 85.0],
[6.0, 92.0]
]
# 使用最小二乘法计算权重w和偏置b
# 公式:w = Σ((x_i - x_mean)(y_i - y_mean)) / Σ((x_i - x_mean)²)
# b = y_mean - w * x_mean
x = np.array([d[0] for d in training_data])
y = np.array([d[1] for d in training_data])
x_mean = np.mean(x)
y_mean = np.mean(y)
w = np.sum((x - x_mean) * (y - y_mean)) / np.sum((x - x_mean) ** 2)
b = y_mean - w * x_mean
print(f"训练数据: {training_data}")
print(f"计算得到: w = {w:.4f}, b = {b:.4f}")
print(f"预测函数: y = {w:.4f} * x + {b:.4f}")
# 预测
for test_x in [3.5, 7, 8]:
pred_y = predict(test_x, w, b)
print(f" 学习 {test_x} 小时 -> 预测分数: {pred_y:.1f}")
服务器真实输出:
训练数据: [[1.0, 35.0], [2.0, 48.0], [3.0, 62.0], [4.0, 75.0], [5.0, 85.0], [6.0, 92.0]]
计算得到: w = 11.6857, b = 25.2667
预测函数: y = 11.6857 * x + 25.2667
学习 3.5 小时 -> 预测分数: 66.2
学习 7 小时 -> 预测分数: 107.1
学习 8 小时 -> 预测分数: 118.8
最小二乘法推导
目标:找到一条直线 y = wx + b,使得所有样本点到直线的垂直距离平方和最小。
误差函数(Loss Function):
E = Σ(y_i - (w × x_i + b))²
求解:对 w 和 b 求偏导,令偏导为0:
∂E/∂w = -2 × Σ(y_i - w×x_i - b) × x_i = 0
∂E/∂b = -2 × Σ(y_i - w×x_i - b) = 0
解方程组得到:
w = Σ((x_i - x_mean)(y_i - y_mean)) / Σ((x_i - x_mean)²)
b = y_mean - w × x_mean
1.3 分类机(Classifier)
分类器将输入映射到离散的类别标签,而不是连续值。
从预测到分类
预测器的输出是连续值(如分数 66.2),而分类器的输出是类别(如"及格"/“不及格”)。
方法:设置一个阈值(threshold),将连续输出转换为类别。
# 简单分类器
def classify(score, threshold=60):
"""根据分数判断是否及格"""
return "及格" if score >= threshold else "不及格"
# 测试
for hours in [1, 2, 3, 4, 5, 6]:
score = predict(hours, w, b)
label = classify(score)
print(f" 学习 {hours} 小时, 分数 {score:.0f} -> {label}")
服务器真实输出:
学习 1 小时, 分数 35 -> 不及格
学习 2 小时, 分数 48 -> 不及格
学习 3 小时, 分数 62 -> 及格
学习 4 小时, 分数 75 -> 及格
学习 5 小时, 分数 85 -> 及格
学习 6 小时, 分数 92 -> 及格
实验2:多分类器与神经网络
2.1 线性分类器的局限
线性分类器只能用一个**超平面(在2D中是直线)**来划分两类数据。
XOR问题:线性不可分
XOR(异或) 是一个经典的线性不可分问题:
| 输入A | 输入B | XOR输出 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
在2D平面上,XOR的输出分布如下:
B=1
│ 1 0
│
B=0───┼───B=1
│
│ 0 1
B=0
A=0 A=1
无法用一条直线将"1"和"0"分开! 这就是线性分类器的局限性。
可视化:线性分类器的局限

(图1:线性分类器无法用一条直线将XOR的两类分开)
2.2 激活函数的意义
激活函数(Activation Function) 是神经网络的灵魂,它引入了非线性,使得神经网络可以拟合任意复杂的函数。
常见激活函数
| 激活函数 | 公式 | 输出范围 | 特点 |
|---|---|---|---|
| Step | 0 if x<0 else 1 |
{0, 1} | 最早使用,不可导 |
| Sigmoid | 1 / (1 + e^(-x)) |
(0, 1) | 平滑,可导,梯度消失 |
| Tanh | (e^x - e^(-x)) / (e^x + e^(-x)) |
(-1, 1) | 零中心,梯度消失 |
| ReLU | max(0, x) |
[0, +∞) | 计算简单,缓解梯度消失 |
Python实现:激活函数对比
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def tanh(x):
return np.tanh(x)
def relu(x):
return np.maximum(0, x)
def step(x):
return np.where(x >= 0, 1, 0)
# 测试各激活函数
x_values = [-2, -1, 0, 1, 2]
print(f"{'x':>4} | {'Sigmoid':>12} | {'Tanh':>12} | {'ReLU':>12} | {'Step':>10}")
print("-" * 60)
for x in x_values:
s = sigmoid(x)
t = tanh(x)
r = relu(x)
st = step(x)
print(f"{x:>4} | {s:>12.4f} | {t:>12.4f} | {r:>12.4f} | {st:>10.0f}")
服务器真实输出:
x | Sigmoid | Tanh | ReLU | Step
------------------------------------------------------------
-2 | 0.1192 | -0.9640 | 0.0000 | 0
-1 | 0.2689 | -0.7616 | 0.0000 | 0
0 | 0.5000 | 0.0000 | 0.0000 | 1
1 | 0.7311 | 0.7616 | 1.0000 | 1
2 | 0.8808 | 0.9640 | 2.0000 | 1
可视化:激活函数对比

(图2:4种常见激活函数的曲线对比)
2.3 神经网络的起源
神经网络的灵感来自于生物大脑:
生物神经元 人工神经元
─────── ─────────
Dendrite ───► 树突 输入 x1, x2, ..., xn
│ │
▼ ▼
Cell Body ───► 细胞体 加权求和 + 偏置
│ │
▼ ▼
Axon ───► 轴突 激活函数
│ │
▼ ▼
Synapse ───► 突触 输出 y
人工神经元的数学模型:
y = activation(Σ(w_i × x_i) + b)
2.4 神经网络的结构
三层神经网络
输入层 隐藏层 输出层
(3个节点) (3个节点) (2个节点)
x1 ──w11──→ h1 ──w'11──→ o1
╲ ╱ ╲ ╱
╲╱ ╲╱
╱╲ ╱╲
╱ ╲ ╱ ╲
x2 ──w22──→ h2 ──w'22──→ o2
╲ ╱ ╱ ╲
╲╱ ╱ ╲
╱╲ ╲ ╱
╱ ╲ ╲ ╱
x3 ──w33──→ h3 ──w'33──→
每个连接都有一个权重 w
全连接(Fully Connected): 每个节点与下一层所有节点相连
参数数量计算
对于网络结构 3-3-2:
输入层 -> 隐藏层:3 × 3 = 9 个权重
隐藏层 -> 输出层:3 × 2 = 6 个权重
偏置:3(隐藏层)+ 2(输出层)= 5 个
总参数:9 + 6 + 5 = 20 个
通用公式:对于网络 n_0 - n_1 - n_2 - ... - n_L:
总参数 = Σ(n_i × n_{i+1}) + Σ(n_i) (i从0到L-1)
↑ ↑
层间权重 每层的偏置
2.5 模型训练的本质
训练的本质是调整权重和偏置,使得网络的输出尽可能接近目标输出。
训练流程
1. 初始化权重(随机或小值)
↓
2. 正向传播(Forward Propagation)
- 输入 -> 隐藏层 -> 输出层
- 计算当前输出
↓
3. 计算误差(Loss)
- Loss = target - output
↓
4. 反向传播(Backward Propagation)
- 将误差从输出层传回输入层
- 计算每个权重对误差的贡献
↓
5. 更新权重
- w_new = w_old - η × ∂Loss/∂w
↓
6. 重复步骤2-5(多轮训练)
2.6 全连接的意义
全连接(Fully Connected) 意味着上一层每个节点都与下一层每个节点相连。
为什么全连接?
- 信息最大化:每个节点都能接收到上一层所有节点的信息
- 表达能力最强:理论上可以拟合任意函数(万能近似定理)
- 梯度传播充分:误差可以传播到每一个权重
计算量分析
全连接层的计算复杂度:
对于层A(n个节点)-> 层B(m个节点):
- 权重矩阵大小:m × n
- 一次前向传播:O(m × n) 次乘法
- 一次反向传播:O(m × n) 次乘法
示例:MNIST网络 784-100-10
输入层 -> 隐藏层:784 × 100 = 78,400 个权重
隐藏层 -> 输出层:100 × 10 = 1,000 个权重
总权重:79,400 个
总结
在本篇博客中,我们学习了:
- 预测器:用线性回归模型根据输入预测输出
- 分类器:用阈值将连续输出转换为类别标签
- 线性分类器的局限:XOR问题无法用一条直线解决
- 激活函数:Sigmoid、Tanh、ReLU等引入非线性
- 神经网络结构:多层神经元,全连接
- 训练的本质:通过调整权重最小化误差
关键公式回顾:
预测器:y = w × x + b
神经元:y = activation(Σ(w_i × x_i) + b)
Sigmoid:σ(x) = 1 / (1 + e^(-x))
参数数量:Σ(n_i × n_{i+1}) + Σ(n_i)
下一篇预告
第2篇:神经网络的正向传播与误差的反向传播
你将学习:
- 矩阵运算在神经网络中的应用
- 信号如何在多层网络中传播
- 误差如何反向传播到每一层
- 每个权重对误差的贡献如何计算
参考文献:
- Tariq Rashid, 《Python神经网络编程》
- Ian Goodfellow 等, 《深度学习》
- MNIST数据库:http://yann.lecun.com/exdb/mnist/
代码仓库:本文所有代码可在服务器 /root/nn_blog/ 目录下找到。
作者:腾讯DevOps工程师 | 最后更新:2026年7月
更多推荐



所有评论(0)