# [cs231n (八)神经网络总结:最小网络案例研究 ][1]

2023-12-27 10:38

本文主要是介绍# [cs231n (八)神经网络总结:最小网络案例研究 ][1],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

cs231n (八)神经网络总结:最小网络案例研究

标签(空格分隔): 神经网络

文章目录

  • [cs231n (八)神经网络总结:最小网络案例研究 ][1]
  • 同类文章
  • 0.回顾
  • 1. 引言
  • 2. 生成一些数据
  • 3. 训练一个softmax线性分类器
      • 1. 初始化参数
      • 2. 计算分数
      • 3. 计算loss
      • 4. 反向传播法计算梯度
      • 6. 现在就可以合并一下得到softmax分类器
  • 4. 训练神经网络
  • 5. 总结
  • 转载和疑问声明
  • 我祝各位帅哥,和美女,你们永远十八岁,嗨嘿嘿~~~

同类文章

cs231n (一)图像分类识别讲了KNN
cs231n (二)讲了线性分类器:SVM和SoftMax
cs231n (三)优化问题及方法
cs231n (四)反向传播
cs231n (五)神经网络 part 1:构建架构
cs231n (六)神经网络 part 2:传入数据和损失
cs231n (七)神经网络 part 3 : 学习和评估
cs231n (八)神经网络总结:最小网络案例研究
cs231n (九)卷积神经网络


0.回顾

cs231n (一)图像分类识别讲了KNN
cs231n (二)讲了线性分类器:SVM和SoftMax
cs231n (三)优化问题及方法
cs231n (四)反向传播
cs231n (五)神经网络 part 1:构建架构
cs231n (六)神经网络 part 2:传入数据和损失
cs231n (七)神经网络 part 3 : 学习和评估

1. 引言

经过前面近七节课的学习训练,我们有了深厚理论基础,和毛毛草草的向量化编程基础、调优基础。。。这牛逼吹的怕了都。

那么现在我们应该开始自己动手解决一个实际问题吧:快来啊。

首先实现线性分类器,然后拓展到神经网络,只要线性网络构建好了,我们拓展到神经网络就会很简单很简单很jian。

2. 生成一些数据

先生成一个螺旋离散数据

N = 100 # number of points per class
D = 2 # dimensionality
K = 3 # number of classes
X = np.zeros((N*K,D)) # data matrix (each row = single example)
y = np.zeros(N*K, dtype='uint8') # class labels
for j in range(K):ix = range(N*j,N*(j+1))r = np.linspace(0.0,1,N) # radiust = np.linspace(j*4,(j+1)*4,N) + np.random.randn(N)*0.2 # thetaX[ix] = np.c_[r*np.sin(t), r*np.cos(t)]y[ix] = j
# lets visualize the data:
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)
plt.show()

1

此时数据是非线性的, 对数据进行标准差标准化已经做过了。

3. 训练一个softmax线性分类器

1. 初始化参数

先在这个分类数据集上训练一个Softmax分类器,Softmax分类器具有线性分数函数,并使用交叉熵损失。

线性分类器的参数由每个类别的权重矩阵W和偏差矢量b组成,先将这些参数初始化为随机数:

# initialize parameters randomly
W = 0.01 * np.random.randn(D,K)
b = np.zeros((1,K))

W = DxC = 2x3

2. 计算分数

得到分数很简答啊:

# compute class scores for a linear classifier
scores = np.dot(X, W) + b

X = NxD = 300x2
scores = NxC

3. 计算loss

损失函数是得到区分目标的关键:其实就是正确的类得分是最高的,并且损失是最低的,如果分类正确。

这里使用的是softmax相关的交叉熵损失,损失函数应该是:

L i = − l o g ( e f y i ∑ j e f j ) \displaystyle Li=-log(\frac{e^{f_{y_i}}}{\sum_je^{f_j}}) Li=log(jefjefyi)

softmax 函数把每一个数据得到三个分数,按照上述公式得到的是标准化概率,并且:
当正确类别概率很小,那么loss会趋近于无穷的。
当正确类别概率接近于1,那么loss会趋近于0的, 因为log(1)=0

$$L = \underbrace{ \frac{1}{N} \sum_i L_i }\text{data loss} + \underbrace{ \frac{1}{2} \lambda \sum_k\sum_l W{k,l}^2 }_\text{regularization loss} \\$$

我们计算得到了分数,那么损失可由上述狮子计算

num_examples = X.shape[0]
# get unnormalized probabilities
exp_scores = np.exp(scores)
# normalize them for each example
probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)

现在得到的概率是:[300 x 3], 每行有三个数值,理论上最大的那个就是对应的正确分类的分数。

corect_logprobs = -np.log(probs[range(num_examples),y])

这里只分配概率给正确分类,损失就是这些对数概率和正则化损失的均值

# compute the loss: average cross-entropy loss and regularization
data_loss = np.sum(corect_logprobs)/num_examples
reg_loss = 0.5*reg*np.sum(W*W)
loss = data_loss + reg_loss

损失越低意味着正确分类的概率越高。

4. 反向传播法计算梯度

这里引入 p k = e f k ∑ j e f j L i = − log ⁡ ( p y i ) p_k = \frac{e^{f_k}}{ \sum_j e^{f_j} } \hspace{1in} L_i =-\log\left(p_{y_i}\right) pk=jefjefkLi=log(pyi),

可以使用链式法则:

∂ L i ∂ f k = p k − 1 ( y i = k ) \frac{\partial L_i }{ \partial f_k } = p_k - \mathbb{1}(y_i = k) fkLi=pk1(yi=k)

好简单哈 p = [0.2, 0.3, 0.5], 0.3是正确的分类, 那么 df = [0.2, -0.7, 0.5]

增加分数向量f的第一个或最后一个元素(不正确类别的分数)会增加损失(由于+0.2和+0.5的正号)增加损失是不好的分类。

然而,增加正确分数的分数对损失有负面影响。 -0.7的梯度告诉我们,增加正确的分数会导致损失 Li 的减少,这是合理的。

probs存储每个例子的所有类(作为行)的概率,为了获得分数上的梯度dscores。

dscores = probs
dscores[range(num_examples),y] -= 1
dscores /= num_examples

最后,我们得到的分数 s c o r e s = n p . d o t ( X , W ) + b scores = np.dot(X,W)+ b scores=np.dotXW+b ,所以分数梯度保存在dscores中),我们现在可以反向传播到W和b:

dW = np.dot(X.T, dscores)
db = np.sum(dscores, axis=0, keepdims=True)
dW += reg*W # don't forget the regularization gradient

###5. 如何参数更新?

现在指导了梯度,指导参数如何影响损失函数,那么就开始更新梯度啦,就是稍微减少点梯度,其实就是迭代啦。

# perform a parameter update
W += -step_size * dW
b += -step_size * db

6. 现在就可以合并一下得到softmax分类器

#Train a Linear Classifier# initialize parameters randomly
W = 0.01 * np.random.randn(D,K)
b = np.zeros((1,K))# some hyperparameters
step_size = 1e-0
reg = 1e-3 # regularization strength# gradient descent loop
num_examples = X.shape[0]
for i in xrange(200):# evaluate class scores, [N x K]scores = np.dot(X, W) + b # compute the class probabilitiesexp_scores = np.exp(scores)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]# compute the loss: average cross-entropy loss and regularizationcorect_logprobs = -np.log(probs[range(num_examples),y])data_loss = np.sum(corect_logprobs)/num_examplesreg_loss = 0.5*reg*np.sum(W*W)loss = data_loss + reg_lossif i % 10 == 0:print "iteration %d: loss %f" % (i, loss)# compute the gradient on scoresdscores = probsdscores[range(num_examples),y] -= 1dscores /= num_examples# backpropate the gradient to the parameters (W,b)dW = np.dot(X.T, dscores)db = np.sum(dscores, axis=0, keepdims=True)dW += reg*W # regularization gradient# perform a parameter updateW += -step_size * dWb += -step_size * db

结果大概是这个样子的。

iteration 0: loss 1.096956
iteration 10: loss 0.917265
iteration 20: loss 0.851503
iteration 30: loss 0.822336
iteration 40: loss 0.807586
iteration 50: loss 0.799448
iteration 60: loss 0.794681
iteration 70: loss 0.791764
iteration 80: loss 0.789920
iteration 90: loss 0.788726
iteration 100: loss 0.787938
iteration 110: loss 0.787409
iteration 120: loss 0.787049
iteration 130: loss 0.786803
iteration 140: loss 0.786633
iteration 150: loss 0.786514
iteration 160: loss 0.786431
iteration 170: loss 0.786373
iteration 180: loss 0.786331
iteration 190: loss 0.786302

经过190次迭代,可以得到训练精度:

# evaluate training set accuracy
scores = np.dot(X, W) + b
predicted_class = np.argmax(scores, axis=1)
print 'training accuracy: %.2f' % (np.mean(predicted_class == y))

准确率是 49%, 看一下学习到边界

2

4. 训练神经网络

其实对于非线性边界用线性分类器确实有点难,现在我们构建一个简单的二层神经网络。

第一层第二层就是这么简单:

# initialize parameters randomly
h = 100 # size of hidden layer
W = 0.01 * np.random.randn(D,h)
b = np.zeros((1,h))
W2 = 0.01 * np.random.randn(h,K)
b2 = np.zeros((1,K))

前向传播的分数可以这样得到:

# evaluate class scores with a 2-layer Neural Network
hidden_layer = np.maximum(0, np.dot(X, W) + b) # note, ReLU activation
scores = np.dot(hidden_layer, W2) + b2

在隐含层添加非线性单元------ReLU。
然后计算loss,分数梯度dscores都和之前一样。
计算梯度的时候先BP到第二层网络,这里也和之前的softmax类似。

# backpropate the gradient to the parameters
# first backprop into parameters W2 and b2
dW2 = np.dot(hidden_layer.T, dscores)
db2 = np.sum(dscores, axis=0, keepdims=True)

由于中间加了一个隐含层,所以我们需要计算隐含层的梯度:

dhidden = np.dot(dscores, W2.T)

还需要回传ReLUd的非线性,很简答啊
r = m a x ( 0 , x ) , d r d x = 1 ( x > 0 ) r = max(0, x), \frac{dr}{dx} = 1(x > 0) r=max(0,x),dxdr=1(x>0)
可以知道梯度通过如果x > 0, 梯度为零如果x < 0

# backprop the ReLU non-linearity
dhidden[hidden_layer <= 0] = 0

那么计算第一层的权重和梯度就是:

# finally into W,b
dW = np.dot(X.T, dhidden)
db = np.sum(dhidden, axis=0, keepdims=True)

好了我们已经完成整个过程了,总结一下。

# initialize parameters randomly
h = 100 # size of hidden layer
W = 0.01 * np.random.randn(D,h)
b = np.zeros((1,h))
W2 = 0.01 * np.random.randn(h,K)
b2 = np.zeros((1,K))# some hyperparameters
step_size = 1e-0
reg = 1e-3 # regularization strength# gradient descent loop
num_examples = X.shape[0]
for i in xrange(10000):# evaluate class scores, [N x K]hidden_layer = np.maximum(0, np.dot(X, W) + b) # note, ReLU activationscores = np.dot(hidden_layer, W2) + b2# compute the class probabilitiesexp_scores = np.exp(scores)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]# compute the loss: average cross-entropy loss and regularizationcorect_logprobs = -np.log(probs[range(num_examples),y])data_loss = np.sum(corect_logprobs)/num_examplesreg_loss = 0.5*reg*np.sum(W*W) + 0.5*reg*np.sum(W2*W2)loss = data_loss + reg_lossif i % 1000 == 0:print "iteration %d: loss %f" % (i, loss)# compute the gradient on scoresdscores = probsdscores[range(num_examples),y] -= 1dscores /= num_examples# backpropate the gradient to the parameters# first backprop into parameters W2 and b2dW2 = np.dot(hidden_layer.T, dscores)db2 = np.sum(dscores, axis=0, keepdims=True)# next backprop into hidden layerdhidden = np.dot(dscores, W2.T)# backprop the ReLU non-linearitydhidden[hidden_layer <= 0] = 0# finally into W,bdW = np.dot(X.T, dhidden)db = np.sum(dhidden, axis=0, keepdims=True)# add regularization gradient contributiondW2 += reg * W2dW += reg * W# perform a parameter updateW += -step_size * dWb += -step_size * dbW2 += -step_size * dW2b2 += -step_size * db2## This prints:iteration 0: loss 1.098744
iteration 1000: loss 0.294946
iteration 2000: loss 0.259301
iteration 3000: loss 0.248310
iteration 4000: loss 0.246170
iteration 5000: loss 0.245649
iteration 6000: loss 0.245491
iteration 7000: loss 0.245400
iteration 8000: loss 0.245335
iteration 9000: loss 0.245292

训练精度是:98%! 厉害了,老铁

# evaluate training set accuracy
hidden_layer = np.maximum(0, np.dot(X, W) + b)
scores = np.dot(hidden_layer, W2) + b2
predicted_class = np.argmax(scores, axis=1)
print 'training accuracy: %.2f' % (np.mean(predicted_class == y))

3

5. 总结

其实从线性到网络我们变化的代码很少,Loss只变了一行,反向传播只不过是加了“中间变量”。


转载和疑问声明

如果你有什么疑问或者想要转载,没有允许是不能转载的哈
赞赏一下能不能转?哈哈,联系我啊,我告诉你呢 ~~
欢迎联系我哈,我会给大家慢慢解答啦~~~怎么联系我? 笨啊~ ~~ 你留言也行

你关注微信公众号1.机器学习算法工程师:2.或者扫那个二维码,后台发送 “我要找朕”,联系我也行啦!

(爱心.gif) 么么哒 ~么么哒 ~么么哒
码字不易啊啊啊,如果你觉得本文有帮助,三毛也是爱!

我祝各位帅哥,和美女,你们永远十八岁,嗨嘿嘿~~~

这篇关于# [cs231n (八)神经网络总结:最小网络案例研究 ][1]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/542848

相关文章

Java反转字符串的五种方法总结

《Java反转字符串的五种方法总结》:本文主要介绍五种在Java中反转字符串的方法,包括使用StringBuilder的reverse()方法、字符数组、自定义StringBuilder方法、直接... 目录前言方法一:使用StringBuilder的reverse()方法方法二:使用字符数组方法三:使用自

MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固 通俗易懂版)

《MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固通俗易懂版)》本文主要讲解了MySQL中的多表查询,包括子查询、笛卡尔积、自连接、多表查询的实现方法以及多列子查询等,通过实际例子和操... 目录复合查询1. 回顾查询基本操作group by 分组having1. 显示部门号为10的部门名,员

Python依赖库的几种离线安装方法总结

《Python依赖库的几种离线安装方法总结》:本文主要介绍如何在Python中使用pip工具进行依赖库的安装和管理,包括如何导出和导入依赖包列表、如何下载和安装单个或多个库包及其依赖,以及如何指定... 目录前言一、如何copy一个python环境二、如何下载一个包及其依赖并安装三、如何导出requirem

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

Python中连接不同数据库的方法总结

《Python中连接不同数据库的方法总结》在数据驱动的现代应用开发中,Python凭借其丰富的库和强大的生态系统,成为连接各种数据库的理想编程语言,下面我们就来看看如何使用Python实现连接常用的几... 目录一、连接mysql数据库二、连接PostgreSQL数据库三、连接SQLite数据库四、连接Mo

Git提交代码详细流程及问题总结

《Git提交代码详细流程及问题总结》:本文主要介绍Git的三大分区,分别是工作区、暂存区和版本库,并详细描述了提交、推送、拉取代码和合并分支的流程,文中通过代码介绍的非常详解,需要的朋友可以参考下... 目录1.git 三大分区2.Git提交、推送、拉取代码、合并分支详细流程3.问题总结4.git push