CS231N Assignment1 SVM 笔记
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
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
输入为:
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 笔记的更多相关文章
- cs231n assignment1 KNN
title: cs231n assignment1 KNN tags: - KNN - cs231n categories: - 机器学习 date: 2019年9月16日 17:03:13 利用KN ...
- SVM 笔记整理
支持向量机 一.支持向量机综述 1.研究思路,从最特殊.最简单的情况开始研究 基本的线性的可分 SVM 解决二分类问题,是参数化的模型.定义类标记为 \(+1\) 和 \(-1\)(区别于感知机,感知 ...
- 笔记:CS231n+assignment1(作业一)
CS231n的课后作业非常的好,这里记录一下自己对作业一些笔记. 一.第一个是KNN的代码,这里的trick是计算距离的三种方法,核心的话还是python和machine learning中非常实用的 ...
- 【cs231n】神经网络笔记笔记2
) # 对数据进行零中心化(重要) cov = np.dot(X.T, X) / X.shape[0] # 得到数据的协方差矩阵 数据协方差矩阵的第(i, j)个元素是数据第i个和第j个维度的协方差. ...
- 【cs231n】最优化笔记
): W = np.random.randn(10, 3073) * 0.0001 # generate random parameters loss = L(X_train, Y_train, W) ...
- cs231n官方note笔记
本文记录官方note中比较新颖和有价值的观点(从反向传播开始) 一 反向传播 1 “反向传播是一个优美的局部过程.在整个计算线路图中,每个门单元都会得到一些输入并立即计算两个东西:1. 这个门的输出值 ...
- [基础]斯坦福cs231n课程视频笔记(三) 训练神经网络
目录 training Neural Network Activation function sigmoid ReLU Preprocessing Batch Normalization 权重初始化 ...
- CS231n 2017 学习笔记01——KNN(K-Nearest Neighbors)
本博客内容来自 Stanford University CS231N 2017 Lecture 2 - Image Classification 课程官网:http://cs231n.stanford ...
- SVM笔记
1.前言 SVM(Support Vector Machine)是一种寻求最大分类间隔的机器学习方法,广泛应用于各个领域,许多人把SVM当做首选方法,它也被称之为最优分类器,这是为什么呢?这篇文章将系 ...
- 【cs231n】图像分类笔记
前言 首先声明,以下内容绝大部分转自知乎智能单元,他们将官方学习笔记进行了很专业的翻译,在此我会直接copy他们翻译的笔记,有些地方会用红字写自己的笔记,本文只是作为自己的学习笔记.本文内容官网链接: ...
随机推荐
- 高颜值开源数据可视化工具——Superset 2.0正式发布!
Superset终于迎来了又一个重大的版本更新.使用superset已经近三年的时间了,其为我们提供了数据可视化的解决方案.也成为了最好的商用BI的替代方案. 在Github上本次更新已经发布 ...
- 从银行数字化转型来聊一聊,火山引擎 VeDI 旗下 ByteHouse 的应用场景
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,火山引擎凭借云原生数据分析平台 ByteHouse,成功入围行业媒体 Internet Deep(互联网周刊 ...
- 大数据 - DWD&DIM 行为数据
我们前面采集的日志数据已经保存到 Kafka 中,作为日志数据的 ODS 层,从 Kafka 的ODS 层读取的日志数据分为 3 类, 页面日志.启动日志和曝光日志.这三类数据虽然都是用户行为数据,但 ...
- SQL Server 事务执行、回滚
MySQL 事务回滚.在执行删除.更新等操作时,防止误操作 生产环境更新数据时必用 begin tran --开启事务 begin--先在事务中 执行 UPDATE Sys_User SET Name ...
- 让 ChatGPT 如虎添翼 2.0
月初写了4个工具,让 ChatGPT 如虎添翼!,时隔二十多天,我又发现了基于ChatGPT的应用,只推最好用的,强烈建议大家都感受一下. 极简搭建 ChatGPT 演示网页 项目地址:https:/ ...
- django DRF
博客目录 web应用模式 api接口 接口测试工具postman restful规范 drf安装 序列化和反序列化 CBV源码分析 drf之APIView分析 drf之Request对象分析 drf- ...
- 面对科技公司的制裁,俄罗斯放出封印7年的神兽:RuTracker
大家好,我是DD! 最近俄乌冲突引发的科技公司站队,Oracle.微软.三星等全球知名科技公司都开始对俄罗斯实施制裁与封锁.就连崇尚自由的开源社区GitHub也发文会严格限制俄罗斯获得维持其咄咄逼人的 ...
- Codeforces Round #656 (Div. 3)部分题解
Codeforces Round #656 (Div. 3)题解 A.Three Pairwise Maximums 解题思路: 依照题意和样例,三个整数x,y,z必须有两个相同且都比第三个数大. 如 ...
- 经典Python案例实现
入门_30个常用python实现 .pdf 一. 二. 三. 四. 五.函数篇 5.1 计算圆的面积 from math import pi as PI def CircleArea(r): if i ...
- Codeforces #698 Div.2 (A~D题)个人题解记录
1478A. Nezzar and Colorful Balls 看半天题,然后才发现是统计最大值. int _; int main() { ios_base::sync_with_stdio(fal ...