分类器训练

R-CNN在完成卷积模型的微调后,额外使用了线性SVM分类器,采用负样本挖掘方法进行训练,参考Hard Negative Mining

线性SVM

参考:

线性SVM分类器

线性SVM分类器-PyTorch实现

线性SVM分类器包含了线性回归+折页损失,其中自定义PyTorch的折页损失实现:

def hinge_loss(outputs, labels):
    """
    折页损失计算
    :param outputs: 大小为(N, num_classes)
    :param labels: 大小为(N)
    :return: 损失值
    """
    num_labels = len(labels)
    corrects = outputs[range(num_labels), labels].unsqueeze(0).T

    # 最大间隔
    margin = 1.0
    margins = outputs - corrects + margin
    loss = torch.sum(torch.max(margins, 1)[0]) / len(labels)

    # # 正则化强度
    # reg = 1e-3
    # loss += reg * torch.sum(weight ** 2)

    return loss

负样本挖掘

实现流程如下:

  1. 设置初始训练集,正负样本数比值为1:1(以正样本数目为基准)
  2. 每轮训练完成后,使用分类器对剩余负样本进行检测,如果检测为正,则加入到训练集中
  3. 重新训练分类器,重复第二步,直到检测精度开始收敛

训练参数

  1. 学习率:1e-4
  2. 动量:0.9
  3. 随步长衰减:每隔4轮衰减一次,参数因子α=0.1
  4. 迭代次数:10
  5. 批量处理:每次训练128个图像,其中32个正样本,96个负样本

训练结果

$ python linear_svm.py 
Epoch 0/9
----------
train - positive_num: 625 - negative_num: 625 - data size: 1152
train Loss: 1.1406 Acc: 0.6424
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0560 Acc: 0.8080
remiam negative size: 365403, acc: 0.8821
Epoch 1/9
----------
train - positive_num: 625 - negative_num: 43397 - data size: 43904
train Loss: 1.0180 Acc: 0.9410
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0426 Acc: 0.9232
remiam negative size: 365403, acc: 0.9965
Epoch 2/9
----------
train - positive_num: 625 - negative_num: 43606 - data size: 44160
train Loss: 1.0063 Acc: 0.9716
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0414 Acc: 0.9241
remiam negative size: 365403, acc: 0.9972
Epoch 3/9
----------
train - positive_num: 625 - negative_num: 43731 - data size: 44288
train Loss: 1.0047 Acc: 0.9767
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0429 Acc: 0.9234
remiam negative size: 365403, acc: 0.9980
Epoch 4/9
----------
train - positive_num: 625 - negative_num: 43773 - data size: 44288
train Loss: 1.0039 Acc: 0.9788
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0421 Acc: 0.9240
remiam negative size: 365403, acc: 0.9980
Epoch 5/9
----------
train - positive_num: 625 - negative_num: 43795 - data size: 44416
train Loss: 1.0039 Acc: 0.9795
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0427 Acc: 0.9234
remiam negative size: 365403, acc: 0.9982
Epoch 6/9
----------
train - positive_num: 625 - negative_num: 43801 - data size: 44416
train Loss: 1.0040 Acc: 0.9786
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0428 Acc: 0.9242
remiam negative size: 365403, acc: 0.9981
Epoch 7/9
----------
train - positive_num: 625 - negative_num: 43808 - data size: 44416
train Loss: 1.0036 Acc: 0.9799
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0429 Acc: 0.9242
remiam negative size: 365403, acc: 0.9981
Epoch 8/9
----------
train - positive_num: 625 - negative_num: 43814 - data size: 44416
train Loss: 1.0035 Acc: 0.9812
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0425 Acc: 0.9242
remiam negative size: 365403, acc: 0.9981
Epoch 9/9
----------
train - positive_num: 625 - negative_num: 43817 - data size: 44416
train Loss: 1.0036 Acc: 0.9802
val - positive_num: 625 - negative_num: 321474 - data size: 322048
val Loss: 1.0424 Acc: 0.9246
remiam negative size: 365403, acc: 0.9981
Training complete in 55m 50s
Best val Acc: 0.924645

经过2轮训练后,分类器损失就开始收敛