svm.ipynb

  • 为SVM实现一个完全矢量化的损失函数
  • 为其解析梯度实现完全矢量化表达式
  • 使用数值梯度检查实现结果
  • 使用验证集调整学习率和正则化
  • 使用 SGD 优化损失函数
  • 可视化最终学习权重

第一部分

1. 一些配置和库的导入

# Run some setup code for this notebook.
import random
import numpy as np
from cs231n.data_utils import load_CIFAR10 # 该函数用于加载CIFAR-10数据集。
import matplotlib.pyplot as plt # 导入matplotlib.pyplot库,并命名为plt,用于绘图 # This is a bit of magic to make matplotlib figures appear inline in the
# notebook rather than in a new window.
# 在Jupyter Notebook中将绘制的图形显示在笔记本中而不是弹出新窗口 %matplotlib inline
plt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plots 绘图默认大小
plt.rcParams['image.interpolation'] = 'nearest' # 设置了图像的插值方式为最近邻插值
plt.rcParams['image.cmap'] = 'gray' # 颜色映射为灰度

2. 导入数据集路径,删除之前冗余的训练集和测试集并重新载入,输出例如Training data shape: (50000, 32, 32, 3),代表训练数据集包含50,000个样本,每个样本的维度是32x32像素,具有3个通道(RGB颜色通道)。

3. 为部分样本的可视化。

4. 训练集、验证集和测试集的划分,并创建了一个小的dev集作为训练数据的子集

mask = range(num_training, num_training + num_validation)
X_val = X_train[mask]
y_val = y_train[mask]
# 选择train中num_training到num_training + num_validation范围的样本作验证集 mask = range(num_training)
X_train = X_train[mask]
y_train = y_train[mask]
# 选择train中的前num_training个样本作训练集 mask = np.random.choice(num_training, num_dev, replace=False)
X_dev = X_train[mask]
y_dev = y_train[mask]
# 从train中随机选择了num_dev个样本作为dev集
# np.random.choice函数用于从num_training个样本中选择num_dev个样本
# replace=False表示不允许重复选择。 mask = range(num_test)
X_test = X_test[mask]
y_test = y_test[mask]
# 从原始test中选择了前num_test个样本作为测试集

5. 将图像数据转化为行向量

X_train = np.reshape(X_train, (X_train.shape[0], -1))
# (X_train.shape[0], -1)表示将数组的第一个维度保持不变(即样本数量),而将后面的维度展平为一维。
# -1的使用是为了自动计算展平后的维度,以保持总元素数量不变。
# 即每个样本的图像数据展为一个长度为32*32*3的行向量

6. 减去图像平均值,注意train,val,test,dev数据集减去的都是train的平均值

并为train、val、test、dev集分别添加一列1向量作为SVM的偏置

# third: append the bias dimension of ones (i.e. bias trick) so that our SVM
# only has to worry about optimizing a single weight matrix W.
X_train = np.hstack([X_train, np.ones((X_train.shape[0], 1))])
X_val = np.hstack([X_val, np.ones((X_val.shape[0], 1))])
X_test = np.hstack([X_test, np.ones((X_test.shape[0], 1))])
X_dev = np.hstack([X_dev, np.ones((X_dev.shape[0], 1))])

第二部分 SVM Classifier

主要完成 cs231n/classifiers/linear_svm.py 当中的svm_loss_naive和svm_loss_vectorized两个函数。
 
1. 带循环的svm loss函数svm_loss_naive
对N个样本的小批量进行操作,数据维度为D,共有C个类别。
输入为权重矩阵W(大小为C*D),小批量数据数组X(大小为N*D),训练标签数组y(大小为N*1),浮点数reg表示正则化强度。
返回为一个元组,包括以单个浮点数表示的损失值,和以与W形状相同的数组表示的相对于权重W的梯度。
在逐图计算损失函数之前预赋值:
dW = np.zeros(W.shape)  # initialize the gradient as zero
# compute the loss and the gradient
num_classes = W.shape[1] # 权重矩阵W(D, C)的列数,即类别的数量C
num_train = X.shape[0] # 数据X(N, D)的行数,即训练样本的数量N
loss = 0.0

计算损失函数并调整dW

for i in range(num_train):
scores = X[i].dot(W) # 第i张图各类别的score
correct_class_score = scores[y[i]] # 正确类别的得分
for j in range(num_classes):
if j == y[i]:
continue # 跳过正确类别
margin = scores[j] - correct_class_score + 1 # note delta = 1
if margin > 0:
loss += margin
dW[:, j] += X[i] #对于错误类别j,将X[i]的特征向量添加到dW的第j列,以增加与非正确类别j相关的梯度
dW[:, y[i]] -= X[i]
# Right now the loss is a sum over all training examples, but we want it
# to be an average instead so we divide by num_train.
loss /= num_train
dW /= num_train
# Add regularization to the loss.
loss += reg * np.sum(W * W)
dW += 2 * reg * W return loss, dW

此时使得svm.py中 naive implementation of the loss 输出结果约为9,检查数值梯度与解析梯度,输出为:

numerical: -5.307963 analytic: -5.307963, relative error: 6.594235e-11
numerical: -0.682609 analytic: -0.682609, relative error: 2.391609e-10
numerical: -13.345338 analytic: -13.345338, relative error: 6.576081e-12
numerical: 14.802119 analytic: 14.802119, relative error: 4.652609e-12
numerical: 10.270928 analytic: 10.270928, relative error: 1.109950e-11
numerical: -8.296183 analytic: -8.296183, relative error: 3.013113e-11
numerical: 16.433458 analytic: 16.433458, relative error: 8.212111e-12
numerical: -6.156451 analytic: -6.156451, relative error: 8.508562e-12
numerical: 16.405473 analytic: 16.405473, relative error: 2.345135e-11
numerical: 18.069155 analytic: 18.069155, relative error: 9.391046e-12
numerical: -4.456779 analytic: -4.456779, relative error: 7.112725e-11
numerical: 11.308422 analytic: 11.308422, relative error: 1.921026e-11
numerical: 14.150021 analytic: 14.150021, relative error: 7.236039e-12
numerical: -19.405984 analytic: -19.405984, relative error: 1.218480e-11
numerical: -2.109591 analytic: -2.109591, relative error: 1.329375e-10
numerical: 3.450493 analytic: 3.450493, relative error: 5.982507e-11
numerical: -7.641039 analytic: -7.641039, relative error: 2.339206e-11
numerical: -22.684454 analytic: -22.684454, relative error: 9.529207e-12
numerical: -8.240884 analytic: -8.240884, relative error: 4.336906e-11
numerical: 11.273042 analytic: 11.273042, relative error: 2.986500e-11

(这个有没有正则化的差异我也没搞懂怎么看)

2. 向量化的的svm loss函数svm_loss_vectorized

def svm_loss_vectorized(W, X, y, reg):

    loss = 0.0
dW = np.zeros(W.shape) # initialize the gradient as zero num_train = X.shape[0]
scores = X.dot(W)
correct_class_scores = scores[np.arange(num_train), y].reshape(-1, 1)
margins = np.maximum(0, scores - correct_class_scores + 1)
margins[np.arange(num_train), y] = 0
loss = np.sum(margins) / num_train + reg * np.sum(W * W) binary = margins
binary[margins > 0] = 1
row_sum = np.sum(binary, axis=1)
binary[np.arange(num_train), y] = -row_sum
dW = X.T.dot(binary) / num_train + 2 * reg * W return loss, dW

第三部分 Stochastic Gradient Descent

 cs231n/classifiers/linear_classifier.py
 首先完成SGD LinearClassifier.train():
输入为:
数据数组X(大小为N*D)
训练标签数组y(大小为N*1)
浮点数learning rate 为优化学习率
浮点数reg表示正则化强度
整数num_iters为优化步数
整数batch_size为每步训练样本数量
布尔变量verbose表示是否打印过程
输出为:
一个包含每次训练迭代损失函数值的列表
class LinearClassifier(object):
def __init__(self):
self.W = None def train(
self,
X,
y,
learning_rate=1e-3,
reg=1e-5,
num_iters=100,
batch_size=200,
verbose=False,
):
num_train, dim = X.shape
num_classes = (
np.max(y) + 1
) # assume y takes values 0...K-1 where K is number of classes
if self.W is None:
# lazily initialize W
self.W = 0.001 * np.random.randn(dim, num_classes) # Run stochastic gradient descent to optimize W
loss_history = []
for it in range(num_iters)
indices = np.random.choice(num_train, batch_size, replace=True)
X_batch = X[indices]
y_batch = y[indices] # evaluate loss and gradient
loss, grad = self.loss(X_batch, y_batch, reg)
loss_history.append(loss) # perform parameter update
self.W -= learning_rate * grad
if verbose and it % 100 == 0: #每一百步打印一次
print("iteration %d / %d: loss %f" % (it, num_iters, loss)) return loss_history

输出为

iteration 0 / 1500: loss 785.501628
iteration 100 / 1500: loss 287.509919
iteration 200 / 1500: loss 107.628805
iteration 300 / 1500: loss 41.988279
iteration 400 / 1500: loss 18.835256
iteration 500 / 1500: loss 9.834987
iteration 600 / 1500: loss 6.770916
iteration 700 / 1500: loss 6.600116
iteration 800 / 1500: loss 5.691690
iteration 900 / 1500: loss 5.231099
iteration 1000 / 1500: loss 5.708499
iteration 1100 / 1500: loss 5.363125
iteration 1200 / 1500: loss 4.935640
iteration 1300 / 1500: loss 5.723507
iteration 1400 / 1500: loss 5.441428
That took 8.358134s

绘制为图像

然后完成LibearSVM.predict函数

输入X输出y

    def predict(self, X):
y_pred = np.zeros(X.shape[0])
scores = X.dot(self.W)
y_pred = np.argmax(scores, axis=1) #np.argmax()可以返回数组中最大元素的索引。
return y_pred

接下来的任务是调整超参数使得准确率上升到0.39左右(刚刚仅有0.37-0.38)

results = {}
best_val = -1 # The highest validation accuracy that we have seen so far.
best_svm = None # The LinearSVM object that achieved the highest validation rate.

为了减少训练时间,先把步数设得比较小,找到合适的参数再调整得大一些

learning_rates = [1.5e-7,1.4e-7,1.3e-7,1.2e-7]#调整超参数
regularization_strengths = [2.5e4,3e4] for lr in learning_rates:
for reg in regularization_strengths:
svm = LinearSVM()
svm.train(X_train, y_train, learning_rate=lr, reg=reg, num_iters=500) # 使用较小的 num_iters 进行训练 # 计算训练集和验证集上的准确率
train_accuracy = np.mean(y_train == svm.predict(X_train))
val_accuracy = np.mean(y_val == svm.predict(X_val)) # 将准确率存储在 results 字典中
results[(lr, reg)] = (train_accuracy, val_accuracy) # 更新最高验证准确率和对应的 LinearSVM 对象
if val_accuracy > best_val:
best_val = val_accuracy
best_svm = svm for lr, reg in sorted(results):
train_accuracy, val_accuracy = results[(lr, reg)]
print('lr %e reg %e train accuracy: %f val accuracy: %f' % (
lr, reg, train_accuracy, val_accuracy)) print('best validation accuracy achieved during cross-validation: %f' % best_val)

最后调出来差不多这样:(1500num_iters)

lr 1.400000e-07 reg 2.100000e+04 train accuracy: 0.368980 val accuracy: 0.374000
lr 1.400000e-07 reg 2.200000e+04 train accuracy: 0.372510 val accuracy: 0.387000
lr 1.400000e-07 reg 2.500000e+04 train accuracy: 0.366163 val accuracy: 0.393000
lr 1.400000e-07 reg 2.700000e+04 train accuracy: 0.364918 val accuracy: 0.384000
lr 1.400000e-07 reg 3.000000e+04 train accuracy: 0.351837 val accuracy: 0.353000
best validation accuracy achieved during cross-validation: 0.393000
 也可用用随机的:(不太会调这个,效果都不怎么好)
np.random.seed(7)

learning_rates = 10**(np.random.rand(5) * 1.5 - 7.5)#[1.4e-7]
regularization_strengths = 10**(np.random.rand(5) * 2 + 3)#[2.1e4,2.2e4,2.5e4,2.7e4,3e4]

绘散点图

在测试集上输出结果

# Evaluate the best svm on test set
y_test_pred = best_svm.predict(X_test)
test_accuracy = np.mean(y_test == y_test_pred)
print('linear SVM on raw pixels final test set accuracy: %f' % test_accuracy)

最后做了一个权重可视化,需要rescale the weights to be between 0 and 255

 
 

CS231N Assignment1 SVM 笔记的更多相关文章

  1. cs231n assignment1 KNN

    title: cs231n assignment1 KNN tags: - KNN - cs231n categories: - 机器学习 date: 2019年9月16日 17:03:13 利用KN ...

  2. SVM 笔记整理

    支持向量机 一.支持向量机综述 1.研究思路,从最特殊.最简单的情况开始研究 基本的线性的可分 SVM 解决二分类问题,是参数化的模型.定义类标记为 \(+1\) 和 \(-1\)(区别于感知机,感知 ...

  3. 笔记:CS231n+assignment1(作业一)

    CS231n的课后作业非常的好,这里记录一下自己对作业一些笔记. 一.第一个是KNN的代码,这里的trick是计算距离的三种方法,核心的话还是python和machine learning中非常实用的 ...

  4. 【cs231n】神经网络笔记笔记2

    ) # 对数据进行零中心化(重要) cov = np.dot(X.T, X) / X.shape[0] # 得到数据的协方差矩阵 数据协方差矩阵的第(i, j)个元素是数据第i个和第j个维度的协方差. ...

  5. 【cs231n】最优化笔记

    ): W = np.random.randn(10, 3073) * 0.0001 # generate random parameters loss = L(X_train, Y_train, W) ...

  6. cs231n官方note笔记

    本文记录官方note中比较新颖和有价值的观点(从反向传播开始) 一 反向传播 1 “反向传播是一个优美的局部过程.在整个计算线路图中,每个门单元都会得到一些输入并立即计算两个东西:1. 这个门的输出值 ...

  7. [基础]斯坦福cs231n课程视频笔记(三) 训练神经网络

    目录 training Neural Network Activation function sigmoid ReLU Preprocessing Batch Normalization 权重初始化 ...

  8. CS231n 2017 学习笔记01——KNN(K-Nearest Neighbors)

    本博客内容来自 Stanford University CS231N 2017 Lecture 2 - Image Classification 课程官网:http://cs231n.stanford ...

  9. SVM笔记

    1.前言 SVM(Support Vector Machine)是一种寻求最大分类间隔的机器学习方法,广泛应用于各个领域,许多人把SVM当做首选方法,它也被称之为最优分类器,这是为什么呢?这篇文章将系 ...

  10. 【cs231n】图像分类笔记

    前言 首先声明,以下内容绝大部分转自知乎智能单元,他们将官方学习笔记进行了很专业的翻译,在此我会直接copy他们翻译的笔记,有些地方会用红字写自己的笔记,本文只是作为自己的学习笔记.本文内容官网链接: ...

随机推荐

  1. THOR:MindSpore 自研高阶优化器源码分析和实践应用

    摘要:这篇文章跟大家分享下THOR的实践应用.THOR算法的部分内容当前已经在MindSpore中开源 本文分享自华为云社区<MindSpore 自研高阶优化器源码分析和实践应用>,原文作 ...

  2. 输入的查询SQL语句,是如何执行的?

    摘要:输入一条语句,返回一个结果,却不知道这条语句在 MySQL 内部的执行过程. 本文分享自华为云社区<一条查询SQL是如何执行的>,作者: 共饮一杯无 . 执行如下SQL,我们看到的只 ...

  3. 一个Camel Multicast组件聚合策略问题的解决过程

    摘要:本文通过案例,发现了一个Camel Multicast组件聚合策略相关的问题.通过查看Camel源代码,找到了问题原因并给出了解决方案.希望本文可以帮助到遇到同样问题的Camel用户. 本文分享 ...

  4. 8款最佳实践,保护你的 IaC 安全!

    基础设施即代码(IaC) 是一种快速发展的技术,利用软件开发原则和实践,用软件配置基础设施.与传统的 IT 基础架构相比,IaC 可以更高效地交付软件.自动化还解锁了弹性配置的能力,该功能可在不同的负 ...

  5. 火山引擎DataLeap如何解决SLA治理难题(一):应用场景与核心概念介绍

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 基于火山引擎分布式治理的理念,数据平台数据治理团队自研了火山引擎DataLeap SLA保障平台,目前已在字节内部 ...

  6. 火山引擎数智平台 VeDI 帮助智能投影仪更懂用户需求

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 当露营成为年轻人的一种全新生活方式后,连带着户外野营帐篷.可折叠桌椅.卡式炉.多人趣味桌游等露营周边市场都迎来新一 ...

  7. MongoDB 副本模式,会映射到本地 127.0.0.1 错误

    基于 MongoDB 读写分离--Windows MongoDB 副本集配置 ,里面配置了一个坑,导致出现下列错误 [2021-05-10 10:06:11.981] [cluster-Cluster ...

  8. 消息总线 —— SpringCloud Bus

    Bus 简介 Spring Cloud Bus 是 Spring Cloud 体系内的消息总线,支持 RabbitMQ 和 Kafka 两种消息中间件.所谓消息总线,简单理解就是一个消息中心,众多微服 ...

  9. 又拍云邵海杨 - 25年Linux老兵,聊聊运维的“术”与“道”

    您好邵总,请您先做个自我介绍吧,聊聊您的履历和现状,让大家更好的认识您,了解您的背景也有助于读者理解后面的采访内容 我是来自又拍云的邵海杨,从1998年开始使用Linux至今快25年了,资深(老鸟)L ...

  10. ABAP 辨析 标准表|排序表|哈希表

    1.文档介绍 本文档将介绍内表的区别和用法,涉及标准表.排序表.哈希表 2.用法与区别 2.1.内表种类 内表顶层为任意表,任意表分为索引表和哈希表,索引表又可分为标准表和排序表,结构如图: 2.2. ...