3-感知机
感知机是最早的AI模型,是一个解决二分类的模型
1.单层感知机
1.1.数学表达
单层感知机的基础表达可以理解成一个线性回归函数,套上一个激活函数。
输入 ,权重,偏移,激活函数,则表达为:
这里进行计算的都是向量,所以区别于回归和,这里输出的是一个类。
而回归输出的是数,输出的是概率。从数学表达上来看,我理解成一个二分类的线性函数,适于做二分类的任务,在坐标轴上找到一条合适的直线,在一定误差的范围内,较好的完成分类。


1.2.区别
与线性回归,全连接,的区别:
他们的骨干完全相同,都是
其中:
- 是输入向量。
- 是权重矩阵(或系数向量)。
- 是偏置。
- 是线性输出()。
所以,它们都共享“全连接”的线性变换结构。 现代神经网络的全连接层(nn.Linear)就是这个线性核心的通用实现。
差异如下:

我个人直接理 解就是,这里需要意识到,不能简单以为加上非激活函数就可以解决异或问题。这是因为单层感知机本质上就决定了是单调线性。
1.3.异或问题
感知机直观来看就一个线性函数,所以无法做到非线性拟合,所以解决不了异或问题
2.多层感知机
2.1.目的
由于单层感知机,无法解决异或问题,深度学习在一段时间内,都没什么发展,后来就出现了多层感知机,得益于其非线性的拟合,能够解决异或问题。
2.2.数学表达
[ \mathbf{h}_1 = \sigma(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1) ] [ \mathbf{h}_2 = \sigma(\mathbf{W}_2 \mathbf{h}_1 + \mathbf{b}_2) ] [ \mathbf{h}_3 = \sigma(\mathbf{W}_3 \mathbf{h}_2 + \mathbf{b}_3) ] [ \mathbf{o} = \mathbf{W}_4 \mathbf{h}_3 + \mathbf{b}_4 ]
其中,隐藏层数,和隐藏层大小,是超参数。

- 隐藏层套激活函数
- 激活函数是非线性拟合的关键
- 先大后小,先缩后扩
最后一层往往直接输出,不需要过激活函数。
其中的设计,多层的情况下,往往底部大点,提取特征,往上慢慢变小,扩张浓缩的特征,这里我觉得可以参考思想。
同时可以在尾层接入来多分类,常用激活函数
2.3.代码
MLP
class MLP(nn.Module):
def __init__(self,input_size,hidden_size,output_size):
super(MLP,self).__init__()
self.fc1 = nn.Linear(input_size,hidden_size)
self.fc2 = nn.Linear(hidden_size,output_size)
self.relu = nn.ReLU()
def forward(self,x):
x = x.view(-1,28*28)
out = self.relu(self.fc1(x))
out = self.fc2(out)
return out
导包和定义
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import time
import os
BATCH_SIZE = 64
LEARNING_RATE = 0.001
EPOCHS = 10
HIDDEN_SIZE = 256 # 隐藏层神经元数量
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
PATIENCE = 3 # 早停耐心值
# 全局变量用于存储训练历史
train_losses = []
train_accuracies = []
test_accuracies = []
def create_data_loaders():
transform = transforms.Compose([
transforms.ToTensor(),
])
train_dataset = datasets.MNIST(
root='./data',
train=True,
download=True,
transform=transform
)
train_loader = DataLoader(
dataset=train_dataset,
batch_size=64,
shuffle=True
)
test_dataset = datasets.MNIST(
root='./data',
train=False,
download=True,
transform=transform
)
test_loader = DataLoader(
dataset=test_dataset,
batch_size=1000,
shuffle=True
)
return train_loader,test_loader
训练函数
def train(epoch,model,train_loader,criterion,optimizer):
model.train()
total_loss = 0
correct = 0
total = 0
start_time = time.time()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(DEVICE), target.to(DEVICE)
optimizer.zero_grad()
output = model(data)
loss = criterion(output,target)
loss.backward()
optimizer.step()
total = total + loss.item()
_, predicted = torch.max(output.data, 1)
total = total + target.size(0)
correct += (predicted == target).sum().item()
if batch_idx % 100 == 0:
elapsed = time.time() - start_time
batches_done = batch_idx + 1
eta = elapsed / max(batches_done, 1) * (len(train_loader) - batches_done)
print(f'Epoch {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} '
f'({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.4f}\tETA: {eta:.1f}s')
end_time = time.time()
avg_loss = total_loss / len(train_loader)
accuracy = 100.* (correct/total)
train_losses.append(avg_loss)
train_accuracies.append(accuracy)
print(
f'\nEpoch {epoch} 训练完成!平均损失:{avg_loss:.4f}, 训练准确率:{accuracy:.2f}% (耗时:{end_time - start_time:.2f}s)')
测试函数
def test(model, test_loader, criterion):
model.eval()
test_loss = 0
correct = 0
total = 0
with torch.no_grad():
for data,target in test_loader:
data, target = data.to(DEVICE), target.to(DEVICE)
output = model(data)
test_loss += criterion(output,target).item()
_, predicted = torch.max(output.data, 1)
total += target.size(0)
correct += (predicted == target).sum().item()
avg_loss = test_loss / len(test_loader)
accuracy = 100. * correct / total
test_accuracies.append(accuracy)
print(f'\n测试集结果:平均损失:{avg_loss:.4f}, 测试准确率:{accuracy:.2f}% ({correct}/{total})')
return accuracy