卷积神经网络与LLaMA分类模型
一、卷积操作基础
卷积是深度学习中用于提取局部特征的核心操作,特别适用于图像识别任务。
自定义二维卷积函数示例
以下函数实现了一个简化版的二维卷积:
def convolve2D(image, kernel, padding=0, strides=1):
kernel = np.flipud(np.fliplr(kernel)) # 进行卷积(交叉相关)
Wk, Hk = kernel.shape
W, H = image.shape
W_out = int(((W - Wk + 2 * padding) / strides) + 1)
H_out = int(((H - Hk + 2 * padding) / strides) + 1)
output = np.zeros((W_out, H_out))
if padding != 0:
padded = np.zeros((W + 2*padding, H + 2*padding))
padded[padding:-padding, padding:-padding] = image
else:
padded = image
for y in range(0, H_out):
for x in range(0, W_out):
region = padded[x*strides:x*strides+Wk, y*strides:y*strides+Hk]
output[x, y] = np.sum(region * kernel)
return output
常见滤波器(以灰度图为例)
# 水平边缘检测
horizontal_filter = np.array([
[1, 1, 1],
[0, 0, 0],
[-1, -1, -1]
])
# 垂直边缘检测
vertical_filter = np.array([
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]
])
# 锐化滤波器
sharpen_filter = np.array([
[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]
])
这些手工设计的卷积核虽然能提取部分边缘特征,但不够通用,且难以组合优化。解决方案是使用可学习的卷积核,这就是 CNN 的核心思想。
二、卷积层结构(多通道 & 多滤波器)
在 RGB 图像中,通常使用每通道分别卷积,再将其结果相加作为最终输出。
# 单个卷积核处理三通道图像
output = convolve2D(R, kernel) + convolve2D(G, kernel) + convolve2D(B, kernel)
若使用多个卷积核,可以将每组卷积结果堆叠成不同的特征图(feature maps)。
三、CNN 在 MNIST 手写数字识别上的应用
模型结构定义(基于 PyTorch)
import torch.nn as nn
import torch.nn.functional as F
class MnistConvNet(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=7, padding=3)
self.conv2 = nn.Conv2d(32, 64, kernel_size=5, padding=2)
self.dropout1 = nn.Dropout2d(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(7*7*64, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = F.relu(self.conv1(x)) # 输出尺寸:28x28 -> 28x28
x = F.max_pool2d(x, 2) # -> 14x14
x = F.relu(self.conv2(x)) # -> 14x14
x = F.max_pool2d(x, 2) # -> 7x7
x = self.dropout1(x)
x = x.view(-1, 7*7*64)
x = F.relu(self.fc1(x))
x = self.dropout2(x)
return self.fc2(x)
四、LLaMA 模型用于序列分类(LlamaForSequenceClassification)
LLaMA 模型是基于 Transformer 的自回归语言模型。它也可以通过在顶部加上分类头来执行序列分类任务。
分类模型结构说明
from transformers import LlamaModel, LlamaPreTrainedModel
import torch.nn as nn
class LlamaForSequenceClassification(LlamaPreTrainedModel):
def __init__(self, config):
super().__init__(config)
self.num_labels = config.num_labels
self.model = LlamaModel(config)
self.score = nn.Linear(config.hidden_size, self.num_labels, bias=False)
self.post_init()
def forward(self, input_ids, attention_mask=None, labels=None):
outputs = self.model(input_ids, attention_mask=attention_mask)
hidden_states = outputs[0]
last_hidden = hidden_states[:, -1, :] # 取最后一个 token 的表示
logits = self.score(last_hidden)
loss = None
if labels is not None:
if self.num_labels == 1:
loss = nn.MSELoss()(logits.view(-1), labels.view(-1))
else:
loss = nn.CrossEntropyLoss()(logits.view(-1, self.num_labels), labels.view(-1))
return {"loss": loss, "logits": logits}
与 LlamaForCausalLM 的区别:
功能 | LlamaForCausalLM | LlamaForSequenceClassification |
---|---|---|
输出维度 | token-level | sequence-level |
输出方式 | 每个 token 的概率分布 | 整个序列一个 logits |
应用任务 | 文本生成 | 分类、回归 |
五、总结
- 卷积操作本质是局部加权求和,可以检测边缘、角点等局部结构;
- CNN 利用可学习的卷积核自动提取多尺度多通道特征,效果远优于人工滤波器;
- LLaMA 可以通过添加一个线性头扩展为分类器,适用于文本情感分析、主题分类等任务;
- 分类版本的 LLaMA 使用的是最后一个 token 的隐状态作为语义表示。