目录
1. 前言
本文是李飞飞cs231n-2022的第一次作业的第5个问题(Higher Level Representations: Image Features)。 前几个问题分别参见:
cs231n-2022-assignment1#Q1:kNN图像分类器实验
cs231n-2022-assignment1#Q2:训练一个支持向量机(SVM)
cs231n-2022-assignment1#Q3:Implementing a softmax classifier
cs231n-2022-assignment1#Q4:Two-Layer Neural Network(Part1)
cs231n-2022-assignment1#Q4:Two-Layer Neural Network(Part2)
本次作业相关的课程内容参见:CS231n Convolutional Neural Networks for Visual Recognition
建议有兴趣的伙伴读原文,过于精彩,不敢搬运。本文可以作为补充阅读材料,主要介绍作业完成过程所涉及一些要点以及关键代码解读。作业的原始starter code可以从Assignment 1 (cs231n.github.io)下载。本文仅涉及完成作业所需要修改的代码,修改的文件涉及以下文件:
+ features.ipynb
2. 数据准备
继承使用上一篇所修改的get_CIFAR10_data()。
from cs231n.data_utils import get_CIFAR10_data
但是,碰到一个小问题。在前几个作业中,模型的输入是要求shape={N,C,H,W}的数据集。但是本题要求的shape又变成{N,C,H,W}。好吧,就当作是练习一下numpy.transpose的使用方法了。
data = get_CIFAR10_data()
for k,v in data.items():
print(('%s: ' % k, v.shape))
X_train = np.transpose(data['X_train'], (0,2,3,1))
y_train = data['y_train']
X_val = np.transpose(data['X_val'], (0,2,3,1))
y_val = data['y_val']
X_test = np.transpose(data['X_test'], (0,2,3,1))
y_test = data['y_test']
print(X_train.shape)
这里用到np.transpose(),它的功能是一种矩阵转置的扩展。矩阵转置是指轴(维度)0(列)和轴(维度)1(行) 的交换,向高维空间扩展后就是多个轴之间的一个置换(permutation)。get_CIFAR10_data输出的数据shape为{N,C,H,W},现在要变为{N,H,W,C},即:轴0保持不变;轴2变为轴1;轴3变为轴2;轴1变为轴3;传给np.transpose()的参数就表示这个置换,即{0,2,3,1},该tuple参数的索引表示目标轴,元素值表示原轴。
3. Extract Features
在前面几题中,都是直接基于图像的像素数据进行训练,取得了不错的性能(50%加的准确率,相比10分类的10%的随机分类性能而言)。但是,对于图像信息的处理,直接针对像素数据进行处理不是最有效的做法。本题的目标是尝试先对图像数据进行特征提取,然后再基于特征数据进行(前面所构建的分类器)模型的训练,看看是不是能够得到进一步的分类性能的提升。
对每一图像计算Histogram of Oriented Gradients (HOG)以及针对HSV颜色空间的Hue channel的颜色直方图(color histogram),然后将这两方面的特征拼接成特征向量用作模型训练的输入数据。
大致来说,HOG捕捉的是图像中的纹理(texture)信息而忽略颜色信息,而颜色直方图则是代表了颜色信息而忽视纹理信息。因此,可以预期两者结合在一起使用应该能够获得比单独使用它们中任何一个更好的效果。
hog_feature()函数
和 color_histogram_hsv()函数都是针对单张图像进行特征提取。而
extract_features()则是对数据集进行批量处理,要注意它除了输入数据集以外,另一个输入参数表示的一个函数列表,内部基于这个函数列表中的每一个函数对每张图像进行特征提取,并将所提取的特征拼接成各图像的特征向量(其实,这个可以看作是后面将要登场的卷积神经网络的前身)。这个是基于回调函数的实现方式,它提供了一个灵活性,可以任意进行特征提取函数的修改或扩展。这个实现方式值得学习。
这些代码都是准备好的,没有coding work,代码解说这里就略过了。
4. 基于特征的SVM分类器
基于以上提取出来的特征向量训练之前构建的SVM分类器,并同样对 learning_rates以及regularization_strengths进行hyperparameter tuning,搜索最优参数。
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
for lr in learning_rates:
for reg in regularization_strengths:
print('lr = {0}, reg = {1}'.format(lr,reg))
tic = time.time()
svm = LinearSVM()
#loss_hist = svm.train(X_train, y_train, learning_rate=1e-7, reg=2.5e4, num_iters=5000, verbose=True)
loss_hist = svm.train(X_train_feats, y_train, learning_rate=lr, reg=reg, num_iters=1500, verbose=True)
y_train_pred = svm.predict(X_train_feats)
training_acc = np.mean(np.squeeze(y_train) == y_train_pred)
#print('training accuracy: %f' % (np.mean(y_train == y_train_pred), ))
y_val_pred = svm.predict(X_val_feats)
val_acc = np.mean(np.squeeze(y_val) == y_val_pred)
#print('validation accuracy: %f' % (np.mean(y_val == y_val_pred), ))
results[(lr,reg)] = (training_acc,val_acc)
toc = time.time()
print('That took %fs' % (toc - tic))
if val_acc > best_val:
best_val = val_acc
best_svm = svm
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
训练完后,在测试集上得到的分类性能为43%。在前面Q2中我们得到的性能为37%,6个百分点的提升还是相当不错的。
5. 基于特征的2层神经网络分类器
对 2层神经网络分类器模型机型关于learning_rate和lr_decay两个参数的优化扫描。
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
for learning_rate in [1e-4,1e-5,1e-6]:
for lr_decay in [0.90,0.95,0.99]:
solver = Solver(net, data,
update_rule='adam',
optim_config={'learning_rate': 1e-4,},
lr_decay=0.95,
num_epochs=10, batch_size=256,
print_every=100)
solver.train()
if best_val_acc < solver.best_val_acc:
best_val_acc = solver.best_val_acc
best_net = net
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
运行得到的最佳val_acc为62.1%,训练集上的train_acc则高达75%,所以存在严重的overfitting。
然后再测试集上进行测试得到的分类精度为60%。相比之前Q4(Part2)得到53.7%也是一个明显的提升。
6. 单独只用某项特征的实验
6.1 HOG only
代码修改只需要以下一行即可。这时就体现出来了extact_features的基于回调函数的实现方式的优势来了。
feature_fns = [hog_feature]
修改这一行代码后重新运行2层神经网络分类器的训练,分别得到58.7%和57.8%的验证集accuracy和测试集accuracy。比上面两个中特征合用的性能要略差一些,符合预期。
6.2 Color Diagram
同样只利用颜色信息作为特征向量是个什么情况呢?
num_color_bins = 10 # Number of bins in the color histogram
feature_fns = [lambda img: color_histogram_hsv(img, nbin=num_color_bins)]
分别得到31.9%和25.3%的验证集accuracy和测试集accuracy。相比只是用HOG特征和两者并用的60%左右的accuracy固然是差很多,但是考虑到这个颜色特征向量只是一个10维的向量(因而运算量会远远小于前者),能够取得这个效果应该是非常不错的。
将num_color_bins增大有没有什么改善的效果呢?
num_color_bins=20:val_acc=0.315; test_acc=0.283.
测试集的准确度略有改善。
终于把这个assignment1全部做完(其实还不能说做完了,很多inline question都没有思考和回答),喘口气,再继续接下来的学习。
本作业的全部完成代码下载链接:斯坦福大学CS231N-2022课程第一个大作业全部代码数据