《Image Classification with Classic and Deep Learning Techniques》复现

1 引言

图像分类作为计算机视觉领域的核心任务,旨在将输入图像映射到离散化的语义类别标签。它在人脸识别、自动驾驶、医疗影像诊断、安防监控等诸多应用场景中均发挥着重要作用。传统的图像分类方法主要基于手工设计的特征描述子,如 SIFT、HOG、LBP 等,结合诸如 Bag of Visual Words (BoVW)、Fisher 向量和支持向量机(SVM)等浅层模型,以其良好的可解释性和资源低需求而著称。然而,这些方法在特征表达能力和端到端优化方面与后起的深度学习模型相比常处于劣势。

近年来,卷积神经网络(CNN)凭借自动学习多层次表征的能力,在大规模数据集(如 ImageNet)上取得了显著性能提升,甚至催生了 ResNet、DenseNet、Inception 等多种变种结构。与此同时,针对小规模或资源受限场景,一些研究者提出了轻量化网络和迁移学习方法,通过在预训练模型的基础上微调以适应目标任务,既保证了较高的准确率,又降低了模型的训练成本。

论文《Image Classification with Classic and Deep Learning Techniques》正是在这样的背景下,应运而生。作者旨在通过在同一小规模数据集和统一评价指标下,系统比较和分析以下几类方法的优劣:

  • 经典特征工程方法:BoVW + SVM,代表了图像分类研究的早期主流思路;
  • 浅层神经网络方法:多层感知机(MLP),作为不借助深度卷积网络的神经网络基线;
  • 迁移学习方法:在 ImageNet 上预训练的 InceptionV3 模型,通过不同程度的层冻结与微调,评估迁移学习的实际收益;
  • 轻量化网络设计:作者自研的 TinyNet,结合深度可分离卷积、残差连接等轻量化技术,以更小的模型参数量追求更优的性能。

该研究具有以下主要贡献:

  1. 公平对比:在固定数据集划分和超参数设置下,对比多种方法的分类准确率、计算效率和资源占用;
  2. 系统分析:深入探讨了不同方法在特征可解释性、收敛速度和泛化能力方面的差异;
  3. 轻量化设计:提出了一种适用于小规模数据集的轻量级 CNN 架构(TinyNet),在参数量不足百万级别时仍可取得接近预训练模型的性能。

本报告遵循论文结构,首先介绍方法框架,随后基于选定的 CIFAR-10 子集进行复现实验,并对结果进行多维度分析,最后给出总结与未来工作展望。


2 方法框架概述

为了保证实验的可复现性与结果的可比性,论文中在同一数据集和评价指标下,分别实现并评估了以下四种图像分类方法:

2.1 经典特征工程:BoVW + SVM

  • 特征提取:采用 SIFT 算法提取图像的局部关键点描述子,获得具有尺度与旋转不变性的特征向量;
  • 词典构建:将训练集所有 SIFT 描述子通过 KMeans 聚类,形成视觉词典(视觉单词);
  • 特征聚合:对每张图像的所有描述子进行词典赋值,统计词频直方图作为全局图像表征;
  • 分类器训练:基于直方图特征,使用线性或核 SVM 完成多分类任务。

该方法具有计算过程清晰、易于解释和调试的优势,但当视觉词典规模较大或特征数量过多时,聚类与直方图计算的时间与空间开销会显著增长。

2.2 浅层神经网络:MLP

  • 输入形式:将原始图像像素或简单预处理后的特征向量进行扁平化;
  • 网络结构:构建包含 2--3 层隐藏层的全连接网络,隐藏单元数量和激活函数(如 ReLU、Tanh)可调;
  • 训练策略:引入 Dropout、L2 正则化与批归一化(BatchNorm)以缓解过拟合;
  • 性能评估:统计不同结构和正则化组合下的分类精度与收敛速度。

MLP 方法直观简单,易于实现,可用于基线性能对比;但其对图像空间结构的信息利用不足,通常难以达到卷积网络的效果。

2.3 迁移学习:InceptionV3 微调

  • 预训练模型:采用在 ImageNet 上训练得到的 InceptionV3 网络作为特征提取器;
  • 模型微调:根据目标任务的类别数替换输出层,并探索冻结前 N 个卷积模块或全网络微调的策略;
  • 数据增强:采用随机裁剪、水平翻转、色彩抖动等增强策略,以提高模型泛化能力;
  • 结果对比:评估不同冻结深度和训练轮次对分类准确率的影响。

迁移学习在小规模数据集上表现优异,可显著提升准确率并缩短训练时间,但需要一定的预训练模型与硬件资源支持。

2.4 轻量化网络:TinyNet 设计

  • 架构原则:基于深度可分离卷积和残差连接,设计参数量与计算量更低的网络;
  • 模块组合:引入瓶颈结构、缩减通道数、使用 1×1 卷积进行降维与升维;
  • 超参数设置:调节网络宽度乘子和深度乘子,以平衡准确率与资源消耗;
  • 整体评估:在相同硬件环境下,比较 TinyNet、BoVW、MLP 与 InceptionV3 的参数量、推理时间和分类性能。

TinyNet 的设计既吸收了经典特征与深度学习的优点,又针对小规模数据集进行了轻量化优化,是面向移动端和嵌入式设备的潜在选择。


3 数据集介绍与加载

本报告选用 CIFAR-10 数据集的子集作为复现实验的数据来源。CIFAR-10 数据集包含 10 个类别的彩色图像,每类 6,000 张,图像分辨率为 32×32。为模拟论文中的小规模场景,我们去除 "frog"、"truck" 两类,保留其余 8 类,并从每类中随机抽取 336 张图像,共计 2,688 张。

下面的 Python 代码示例展示了在 Colab 环境中加载 CIFAR-10、进行抽样并完成 70%/30% 划分的流程:

python 复制代码
# Core data loading and splitting for CIFAR-10 subset
from torchvision.datasets import CIFAR10
from sklearn.model_selection import train_test_split
import random, cv2

# Download CIFAR-10
train_ds = CIFAR10('/content/data', train=True, download=True)
test_ds  = CIFAR10('/content/data', train=False, download=True)

# Define and filter classes
define = ['airplane','automobile','bird','cat','deer','dog','horse','ship']
imgs, labels = [], []
for ds in (train_ds, test_ds):
    for img, lbl in zip(ds.data, ds.targets):
        if ds.classes[lbl] in define:
            gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            imgs.append(gray)
            labels.append(define.index(ds.classes[lbl]))

# Sample 336 per class and split 70/30
data = list(zip(imgs, labels))
sampled = []
for cls in range(len(define)):
    cls_data = [d for d in data if d[1]==cls]
    sampled.extend(random.sample(cls_data, 336))
X, y = zip(*sampled)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=42)

4 复现实验

在本小节中,我们基于前面介绍的四种方法,在选取的 CIFAR-10 子集(8 类×336 张样本,70%/30% 划分)上逐步复现并评估各方法的分类性能。

3.1 BoVW + SVM 基线实验

实验设置

数据集:CIFAR-10 子集,8 个类别,每类随机抽样 336 张,共 2,688 张;70% 用于训练,30% 用于测试;

特征提取:采用 OpenCV 中的 SIFT 算法,窗口无表面(dense)提取关键点描述子;

视觉词典:使用 KMeans 聚类构建词典;

分类器:基于 BoVW 直方图特征,选用 RBF 核的 SVM(C=1.0)进行训练;

评估指标:测试集分类准确率。

核心代码:

python 复制代码
sift = cv2.SIFT_create()
desc_list = []
for img in X_train:
    kp, des = sift.detectAndCompute(img, None)
    if des is not None:
        desc_list.append(des)
descriptors = np.vstack(desc_list)


k = 100  # 可尝试 50,100,200 等
kmeans = KMeans(n_clusters=k, random_state=42).fit(descriptors)


def bovw_hist(img):
    _, des = sift.detectAndCompute(img, None)
    hist = np.zeros(k, dtype=int)
    if des is not None:
        words = kmeans.predict(des)
        for w in words:
            hist[w] += 1
    return hist

X_train_feats = np.array([bovw_hist(im) for im in X_train])
X_test_feats  = np.array([bovw_hist(im) for im in X_test])


clf = SVC(kernel='rbf', C=1.0, random_state=42)
clf.fit(X_train_feats, y_train)
y_pred = clf.predict(X_test_feats)
acc = accuracy_score(y_test, y_pred)
print(f"BoVW + SVM 准确率:{acc:.4f}")

结果

不同词典规模下的测试集准确率如下:

k=50:约 27.00%

k=100:约 26.02%

k=200:约 26.32%

词典规模 k=100 时,BoVW + SVM 在测试集上取得 26.02% 的准确率。

图表展示

小结:在小规模子集上,BoVW + SVM 方法能够达到约 26% 的分类准确率,随着词典规模增大精度略有提升,但整体表现仍远落后于深度学习模型。该基线为后续 MLP、迁移学习和轻量网络的性能对比提供了参考。

BoVW + SVM 小结:

BoVW + SVM 方法在小规模 CIFAR-10 子集上,随着词典规模从 50 增大到 200,测试准确率从约 27.00% 提升到约 26.32%。整体准确率在 26% 左右,虽不及深度学习模型,但展示了经典特征提取和浅层分类器在资源受限场景下的可行性。

以下是第 4 章复现实验中剩余三部分的初稿,你可以根据实际运行结果再补充数值和图表。


4.2 MLP 基线实验

实验目的

在 BoVW + SVM 基线之外,使用一个最简单的多层感知机(Multi-Layer Perceptron, MLP)来验证深度网络在本任务上的表现提升。

实验设置

  • 输入特征:将原始灰度图像拉平成长度 32×32 = 1024 的向量;

  • 网络结构

    • 输入层 1024 单元
    • 隐藏层 1:512 单元,ReLU 激活
    • 隐藏层 2:256 单元,ReLU 激活
    • 输出层:8 单元,Softmax
  • 超参数

    • 学习率 0.001,Adam 优化器
    • 批大小 64,训练 30 个 epoch
    • 交叉熵损失

核心代码示例

python 复制代码
Define MLP model
class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(1024, 512), nn.ReLU(),
            nn.Linear(512, 256),  nn.ReLU(),
            nn.Linear(256, 8)
        )
    def forward(self, x):
        return self.net(x)

model = MLP().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3)

# 4. Training loop with metric collection
train_acc_list, val_acc_list = [], []
train_loss_list, val_loss_list = [], []
num_epochs = 30

for epoch in range(1, num_epochs + 1):
    # Train
    model.train()
    running_loss, correct, total = 0.0, 0, 0
    for x_batch, y_batch in train_loader:
        x_batch, y_batch = x_batch.to(device), y_batch.to(device)
        optimizer.zero_grad()
        outputs = model(x_batch)
        loss = criterion(outputs, y_batch)
        loss.backward()
        optimizer.step()
        running_loss += loss.item() * x_batch.size(0)
        preds = outputs.argmax(dim=1)
        correct += (preds == y_batch).sum().item()
        total += y_batch.size(0)
    train_loss_list.append(running_loss / total)
    train_acc_list.append(correct / total)

    # Validate
    model.eval()
    val_loss, val_correct, val_total = 0.0, 0, 0
    with torch.no_grad():
        for x_batch, y_batch in test_loader:
            x_batch, y_batch = x_batch.to(device), y_batch.to(device)
            outputs = model(x_batch)
            loss = criterion(outputs, y_batch)
            val_loss += loss.item() * x_batch.size(0)
            preds = outputs.argmax(dim=1)
            val_correct += (preds == y_batch).sum().item()
            val_total += y_batch.size(0)
    val_loss_list.append(val_loss / val_total)
    val_acc_list.append(val_correct / val_total)

    print(f"Epoch {epoch}: Train Loss={train_loss_list[-1]:.4f}, "
          f"Train Acc={train_acc_list[-1]:.4f}, "
          f"Val Loss={val_loss_list[-1]:.4f}, "
          f"Val Acc={val_acc_list[-1]:.4f}")

结果

小结

MLP 模型在同样的 CIFAR-10 子集上,将分类准确率从 BoVW + SVM 的 ~26% 提升至 ~31%,说明端到端神经网络能更好地学习图像表征。

训练集准确率最终达到 ~52%,而验证集准确率在 ~31% 附近波动,验证损失也表现出一定程度的平稳性与波动,提示模型在后期略有过拟合。

综合来看,MLP 虽比经典特征方法效果更好,但相对于深度卷积网络表现仍有限,需要通过预训练迁移学习或更深层次的网络架构(如 TinyNet)进一步提升性能。

以下是仅"4.3 迁移学习:InceptionV3 微调实验"部分的完整内容,可直接粘贴到报告中:


4.3 迁移学习:InceptionV3 微调实验

实验目的

通过在 ImageNet 上预训练的 InceptionV3 模型进行两阶段微调,验证迁移学习在小规模数据集上的效果提升。

实验设置

  • 模型结构 :加载 aux_logits=True 的 InceptionV3,替换主输出层和辅助输出层为 8 类全连接;
  • 冻结策略:阶段1(5 epochs)冻结除全连接层外的所有参数;阶段2(10 epochs)全部解冻微调;
  • 优化器与学习率:阶段1 对新层使用 Adam(lr=1e-3);阶段2 全网络使用 Adam(lr=1e-4);
  • 数据增强:随机裁剪、水平翻转;
  • 批大小:32;
  • 损失函数:主输出交叉熵 + 0.4×辅助输出交叉熵。

核心代码

python 复制代码
# 1. 设备设置
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

# 2. 自定义 Dataset,将灰度图转换为 RGB Tensor
class GrayscaleCIFARSubset(Dataset):
    def __init__(self, images, labels, transform=None):
        self.images = images  # List of H×W uint8 arrays
        self.labels = labels  # List of ints
        self.transform = transform
        
    def __len__(self):
        return len(self.labels)
    
    def __getitem__(self, idx):
        img = Image.fromarray(self.images[idx])  # PIL grayscale
        img = img.convert("RGB")                 # 转为 3 通道
        if self.transform:
            img = self.transform(img)
        return img, self.labels[idx]

# 3. 数据变换与 DataLoader
train_transform = transforms.Compose([
    transforms.Resize((299,299)),
    transforms.RandomResizedCrop(299),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.5]*3, [0.5]*3),
])
val_transform = transforms.Compose([
    transforms.Resize((299,299)),
    transforms.CenterCrop(299),
    transforms.ToTensor(),
    transforms.Normalize([0.5]*3, [0.5]*3),
])


train_ds = GrayscaleCIFARSubset(X_train, y_train, transform=train_transform)
val_ds   = GrayscaleCIFARSubset(X_test,  y_test,  transform=val_transform)

train_loader = DataLoader(train_ds, batch_size=32, shuffle=True,  num_workers=0)
val_loader   = DataLoader(val_ds,   batch_size=32, shuffle=False, num_workers=0)

# 4. 加载 InceptionV3,设置 aux_logits=True
weights = Inception_V3_Weights.DEFAULT
model = models.inception_v3(weights=weights, aux_logits=True)
# 替换输出层
model.fc = nn.Linear(model.fc.in_features, 8)
model.AuxLogits.fc = nn.Linear(model.AuxLogits.fc.in_features, 8)
model = model.to(device)

# 5. 阶段 1:冻结除新层外的所有参数
for name, param in model.named_parameters():
    if "fc" not in name and "AuxLogits.fc" not in name:
        param.requires_grad = False
optimizer = optim.Adam(
    list(model.fc.parameters()) + list(model.AuxLogits.fc.parameters()),
    lr=1e-3
)
criterion = nn.CrossEntropyLoss()

# 6. 训练/验证函数(融合 auxiliary loss)
def train_epoch(loader):
    model.train()
    total_loss = correct = total = 0
    for imgs, labels in loader:
        imgs, labels = imgs.to(device), labels.to(device)
        optimizer.zero_grad()
        outputs, aux_outputs = model(imgs)
        loss_main = criterion(outputs, labels)
        loss_aux  = criterion(aux_outputs, labels)
        loss = loss_main + 0.4 * loss_aux
        loss.backward()
        optimizer.step()
        total_loss += loss_main.item() * imgs.size(0)
        preds = outputs.argmax(dim=1)
        correct += (preds == labels).sum().item()
        total += labels.size(0)
    return total_loss/total, correct/total

def eval_epoch(loader):
    model.eval()
    total_loss = correct = total = 0
    with torch.no_grad():
        for imgs, labels in loader:
            imgs, labels = imgs.to(device), labels.to(device)
            outputs = model(imgs)
            # outputs is a single tensor when eval
            loss = criterion(outputs, labels)
            total_loss += loss.item() * imgs.size(0)
            preds = outputs.argmax(dim=1)
            correct += (preds == labels).sum().item()
            total += labels.size(0)
    return total_loss/total, correct/total
# 7. 记录列表
train_losses, train_accs = [], []
val_losses,   val_accs   = [], []

# 8. 阶段 1 训练 5 epochs
for epoch in range(1, 6):
    tl, ta = train_epoch(train_loader)
    vl, va = eval_epoch(val_loader)
    train_losses.append(tl); train_accs.append(ta)
    val_losses.append(vl);   val_accs.append(va)
    print(f"Phase1 Epoch {epoch}: Train Acc={ta:.4f}, Val Acc={va:.4f}")

# 9. 阶段 2:解冻所有参数,微调 10 epochs
for param in model.parameters():
    param.requires_grad = True
optimizer = optim.Adam(model.parameters(), lr=1e-4)

for epoch in range(6, 16):
    tl, ta = train_epoch(train_loader)
    vl, va = eval_epoch(val_loader)
    train_losses.append(tl); train_accs.append(ta)
    val_losses.append(vl);   val_accs.append(va)
    print(f"Phase2 Epoch {epoch}: Train Acc={ta:.4f}, Val Acc={va:.4f}")

结果展示

复制代码
Phase1 Epoch 1: Train Acc=0.2329, Val Acc=0.4287
Phase1 Epoch 2: Train Acc=0.3509, Val Acc=0.4362
Phase1 Epoch 3: Train Acc=0.4019, Val Acc=0.4796
Phase1 Epoch 4: Train Acc=0.4003, Val Acc=0.5068
Phase1 Epoch 5: Train Acc=0.4258, Val Acc=0.5204
Phase2 Epoch 6: Train Acc=0.4689, Val Acc=0.6506
Phase2 Epoch 7: Train Acc=0.6114, Val Acc=0.7546
Phase2 Epoch 8: Train Acc=0.6688, Val Acc=0.7646
Phase2 Epoch 9: Train Acc=0.6885, Val Acc=0.7819
Phase2 Epoch 10: Train Acc=0.7060, Val Acc=0.8017
Phase2 Epoch 11: Train Acc=0.7379, Val Acc=0.8079
Phase2 Epoch 12: Train Acc=0.7661, Val Acc=0.8030
Phase2 Epoch 13: Train Acc=0.7788, Val Acc=0.7831
Phase2 Epoch 14: Train Acc=0.7927, Val Acc=0.8191
Phase2 Epoch 15: Train Acc=0.7879, Val Acc=0.7968

小结

在阶段1(冻结大部分层)训练5个周期后,验证准确率从约42.9%提升至52.0%,表明仅微调新加的全连接层即可获得初步性能提升。

阶段2(全网络微调)中,验证准确率进一步快速上升,最高达到约81.9%,最终在第15个周期保持在约79.7%,远超 BoVW 和 MLP 基线。

损失曲线显示,训练与验证损失在微调阶段迅速下降并趋于平稳,表明模型已较好收敛且过拟合程度可控。

总体来看,InceptionV3 的迁移学习显著提升了小规模数据集的分类性能,证明预训练特征在此任务中的有效性.。


4.4 轻量网络:TinyNet 设计与评估

实验目的

在保证较低参数量和计算开销的前提下,从零设计一个小型卷积网络(TinyNet),评估其在小规模图像分类任务上的性能。

网络结构

复制代码
Input (3×32×32)
→ Conv(3→32, 3×3, padding=1) + ReLU
→ MaxPool(2×2)
→ Conv(32→64, 3×3, padding=1) + ReLU
→ MaxPool(2×2)
→ Conv(64→128, 3×3, padding=1) + ReLU
→ AdaptiveAvgPool2d(1×1)
→ Flatten → FC(128→8)

实验设置

  • 数据增强:随机水平翻转;
  • 归一化:通道均值/标准差 = 0.5;
  • 批大小:64;
  • 优化器:Adam,学习率 1e-3;
  • 训练轮数:30 epochs;
  • 损失函数:交叉熵。

核心代码

python 复制代码
class TinyNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 32, 3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(64,128, 3, padding=1), nn.ReLU(),
            nn.AdaptiveAvgPool2d((1,1))
        )
        self.classifier = nn.Linear(128, 8)
    
    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        return self.classifier(x)

model = TinyNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3)

结果

复制代码
Epoch  1: Train Acc=0.1435, Val Acc=0.1846
Epoch  2: Train Acc=0.1946, Val Acc=0.2230
Epoch  3: Train Acc=0.2387, Val Acc=0.2912
Epoch  4: Train Acc=0.2749, Val Acc=0.2924
Epoch  5: Train Acc=0.3169, Val Acc=0.3247
Epoch  6: Train Acc=0.3158, Val Acc=0.3408
Epoch  7: Train Acc=0.3371, Val Acc=0.3395
Epoch  8: Train Acc=0.3493, Val Acc=0.3606
Epoch  9: Train Acc=0.3482, Val Acc=0.3779
Epoch 10: Train Acc=0.3721, Val Acc=0.4213
Epoch 11: Train Acc=0.3929, Val Acc=0.3730
Epoch 12: Train Acc=0.3918, Val Acc=0.4052
Epoch 13: Train Acc=0.4040, Val Acc=0.4114
Epoch 14: Train Acc=0.4221, Val Acc=0.4349
Epoch 15: Train Acc=0.4312, Val Acc=0.4188
Epoch 16: Train Acc=0.4264, Val Acc=0.4399
Epoch 17: Train Acc=0.4402, Val Acc=0.4387
Epoch 18: Train Acc=0.4428, Val Acc=0.4374
Epoch 19: Train Acc=0.4476, Val Acc=0.4523
Epoch 20: Train Acc=0.4657, Val Acc=0.4436
Epoch 21: Train Acc=0.4705, Val Acc=0.4263
Epoch 22: Train Acc=0.4833, Val Acc=0.4634
Epoch 23: Train Acc=0.4848, Val Acc=0.4486
Epoch 24: Train Acc=0.4716, Val Acc=0.4820
Epoch 25: Train Acc=0.4955, Val Acc=0.4845
Epoch 26: Train Acc=0.5077, Val Acc=0.4870
Epoch 27: Train Acc=0.5061, Val Acc=0.4870
Epoch 28: Train Acc=0.5152, Val Acc=0.4449
Epoch 29: Train Acc=0.5024, Val Acc=0.4696
Epoch 30: Train Acc=0.5045, Val Acc=0.5192

小结

  • TinyNet 在第 1 epoch 即实现约18.5%的验证准确率,随着训练逐渐提升至约42%--48%区间,最终在第 30 epoch 达到约51.9%。
  • 训练与验证曲线基本同步,验证损失整体呈下降趋势,仅在少数 epoch 出现小幅波动,说明模型收敛良好且过拟合有限。
  • 相较于 BoVW、MLP 和 InceptionV3,TinyNet 在参数量远小于 InceptionV3 的情况下仍取得约52%的准确率,展现了轻量化设计的有效性和应用潜力。

5 结果分析与讨论

本节将对 BoVW、MLP、InceptionV3 和 TinyNet 四种方法在相同数据集下的性能进行横向对比,并分析各方法的优势与不足。

5.1 性能对比表

方法 测试准确率 参数量 训练时间 资源需求
BoVW + SVM ~26.02% -- CPU 可运行
MLP ~31% ~0.6M 低--中 CPU/GPU 均可
InceptionV3 FT ~79.68% ~23M GPU 必需
TinyNet ~51.92% ~0.1M 轻量 GPU/CPU

5.2 优势与不足

  • BoVW + SVM:实现简单、可解释性强;性能较低,不适合复杂场景。
  • MLP:端到端学习更有效,轻量易实现;对空间结构利用不足,表现有限。
  • InceptionV3 微调:性能最高,预训练优势明显;参数量大,训练与部署成本高。
  • TinyNet:在轻量化与性能间取得平衡;性能介于经典与迁移学习之间,可用于资源受限场景。

5.3 过拟合与泛化

  • InceptionV3 在微调阶段训练与验证曲线拟合良好,未见严重过拟合;
  • TinyNet 和 MLP 验证准确率波动较小,说明数据增强与正则化策略较为有效;
  • BoVW 方法无训练曲线,但静态性能固化,不存在过拟合风险。

6 结论与未来工作展望

6.1 主要结论

  • 经典特征工程方法(BoVW + SVM)提供了可解释的基线,适用于计算资源极其受限场景;
  • 简单的 MLP 能够提升性能,但受限于结构,对图像空间信息利用不足;
  • 迁移学习(InceptionV3 微调)在小规模数据集上表现最优,但成本较高;
  • TinyNet 在参数量与性能间实现了良好折中,是资源受限下的有效选择。

6.2 实践建议

  • 资源充足且追求高精度:优先采用预训练模型微调;
  • 资源受限或移动端部署:可选择 TinyNet 或 MLP,根据具体精度需求平衡;
  • 快速原型与可解释性需求:BoVW + SVM 简单易用,可快速验证想法。

6.3 未来工作展望

  • 探索更高效的轻量化网络结构,如 MobileNetV3、EfficientNet-Lite;
  • 引入半监督学习或自监督预训练,以增强小规模数据集上的泛化能力;
  • 运用元学习或神经架构搜索自动设计更优轻量网络。