当前位置: 首页 > news >正文

一步一步用numpy实现神经网络各种层

1. 首先准备一下数据

if __name__ == "__main__":data = np.array([[2, 1, 0],[2, 2, 0],[5, 4, 1],[4, 5, 1],[2, 3, 0],[3, 2, 0],[6, 5, 1],[4, 1, 0],[6, 3, 1],[7, 4, 1]])x = data[:, :-1]y = data[:, -1]for epoch in range(1000):...

2. 实现Softmax+CrossEntropy层

单独求softmax层有点麻烦, 将softmax+entropy一起求导更方便。

假设对于输入向量 ( x 1 , x 2 , x 3 ) (x_1, x_2, x_3) (x1,x2,x3), 则对应的Loss为:

L = − ∑ i = 1 C y i ln ⁡ p i = − ( y 1 ln ⁡ p 1 + y 2 ln ⁡ p 2 + y 3 ln ⁡ p 3 ) \begin{align*} L&=-\sum_{i=1}^Cy_i \ln p^i \\ &=-(y_1\ln p_1+y_2\ln p_2+y_3\ln p_3) \end{align*} L=i=1Cyilnpi=(y1lnp1+y2lnp2+y3lnp3)

其中 y i y_i yi为ground truth, 为one-hot vector. p i p_i pi为输出概率。

p 1 = e x 1 e x 1 + e x 2 + e x 3 p 2 = e x 2 e x 1 + e x 2 + e x 3 p 3 = e x 3 e x 1 + e x 2 + e x 3 p_1=\frac{e^{x_1}}{e^{x_1}+e^{x_2}+e^{x_3}}\\ p_2=\frac{e^{x_2}}{e^{x_1}+e^{x_2}+e^{x_3}}\\ p_3=\frac{e^{x_3}}{e^{x_1}+e^{x_2}+e^{x_3}}\\ p1=ex1+ex2+ex3ex1p2=ex1+ex2+ex3ex2p3=ex1+ex2+ex3ex3
则偏导为
∂ L ∂ x 1 = − y 1 1 p 1 ∗ ∂ p 1 ∂ x 1 − y 2 1 p 2 ∗ ∂ p 2 ∂ x 1 − y 3 1 p 3 ∗ ∂ p 3 ∂ x 1 = − y 1 1 p 1 ∗ e x 1 ∗ ( e x 1 + e x 2 + e x 3 ) − e x 1 ∗ e x 1 ( e x 1 + e x 2 + e x 3 ) 2 − y 2 1 p 2 ∗ − e x 2 ∗ e x 1 ( e x 1 + e x 2 + e x 3 ) 2 − y 3 1 p 3 ∗ − e x 3 ∗ e x 1 ( e x 1 + e x 2 + e x 3 ) 2 = − y 1 1 p 1 ( p 1 ∗ p 2 + p 1 ∗ p 3 ) − y 2 1 p 2 ( − p 1 ∗ p 2 ) − y 3 1 p 3 ( − p 1 ∗ p 3 ) = − y 1 ( p 2 + p 3 ) + y 2 ∗ p 2 + y 3 ∗ p 3 = − y 1 ( 1 − p 1 ) + y 2 ∗ p 1 + y 3 ∗ p 1 = y 1 ( p 1 − 1 ) + y 2 ∗ p 1 + y 3 ∗ p 1 \begin{align*} \frac{\partial L}{\partial x_1} &= -y_1\frac{1}{p_1}*\frac{\partial p_1}{\partial x_1} - y_2\frac{1}{p_2}*\frac{\partial p_2}{\partial x_1} - y_3\frac{1}{p_3}*\frac{\partial p_3}{\partial x_1} \\ &= -y_1\frac{1}{p_1} * \frac{e^{x_1} * (e^{x_1}+e^{x_2}+e^{x_3})-e^{x_1}*e^{x_1}}{(e^{x_1}+e^{x_2}+e^{x_3})^2} \\ &\quad\quad-y_2\frac{1}{p_2}*\frac{-e^{x_2}*e^{x_1}}{{(e^{x_1}+e^{x_2}+e^{x_3})^2}}\\ &\quad\quad-y_3\frac{1}{p_3}*\frac{-e^{x_3}*e^{x_1}}{{(e^{x_1}+e^{x_2}+e^{x_3})^2}}\\ &=-y_1\frac{1}{p_1}(p_1*p_2+p_1*p_3)\\ &\quad\quad -y_2\frac{1}{p_2}(-p_1*p_2)\\ &\quad\quad -y_3\frac{1}{p_3}(-p_1*p_3)\\ &=-y1(p_2+p_3)+y_2*p_2+y_3*p_3\\ &=-y_1(1-p_1)+y_2*p_1+y_3*p_1\\ &=y_1(p_1-1)+y_2*p_1+y_3*p_1 \end{align*} x1L=y1p11x1p1y2p21x1p2y3p31x1p3=y1p11(ex1+ex2+ex3)2ex1(ex1+ex2+ex3)ex1ex1y2p21(ex1+ex2+ex3)2ex2ex1y3p31(ex1+ex2+ex3)2ex3ex1=y1p11(p1p2+p1p3)y2p21(p1p2)y3p31(p1p3)=y1(p2+p3)+y2p2+y3p3=y1(1p1)+y2p1+y3p1=y1(p11)+y2p1+y3p1

同理:
∂ L ∂ x 2 = y 1 ∗ p 2 + y 2 ( p 2 − 1 ) + y 3 ∗ p 2 ∂ L ∂ x 3 = y 1 ∗ p 3 + y 2 p 3 + y 3 ∗ ( p 3 − 1 ) \frac{\partial L}{\partial x_2}=y_1*p_2+y_2(p_2-1)+y_3*p_2\\ \frac{\partial L}{\partial x_3}=y_1*p_3+y_2p_3+y_3*(p_3-1) x2L=y1p2+y2(p21)+y3p2x3L=y1p3+y2p3+y3(p31)

y 1 = 1 y_1=1 y1=1时, 对应的导数为 ( p 1 − 1 , p 2 , p 3 ) (p1-1, p_2, p_3) (p11,p2,p3). 当 y 2 = 1 y_2=1 y2=1时,对应的导数为: ( p 1 , p 2 − 1 , p 3 ) (p_1, p2-1, p3) (p1,p21,p3).

例如求得概率为 ( 0.2 , 0.3 , 0.5 ) (0.2, 0.3, 0.5) (0.2,0.3,0.5), label为 ( 0 , 0 , 1 ) (0, 0, 1) (0,0,1), 则导数为 ( 0.2 , 0.3 , − 0.5 ) (0.2, 0.3, -0.5) (0.2,0.3,0.5)

python代码为:

注意求softmax时需要np.exp(x-np.max(x, axis=1, keepdims=True))防止指数运算溢出。

class Softmax:def __init__(self, n_classes):self.n_classes = n_classesdef forward(self, x, y):prob = np.exp(x-np.max(x, axis=1, keepdims=True))prob /= np.sum(prob, axis=1, keepdims=True)# 选出y==1位置的概率loss = -np.sum(np.log(prob[np.arange(len(y), y])) / len(y)self.grad = prob.copy()self.grad[np.arange(len(y), y] -= 1"""因为后面求导数都是直接np.sum而不是np.mean, 因此这里mean一次就可以了"""self.grad /= len(y)  return prob, lossdef backward(self):return self.grad

3. 单独的CrossEntropy

python代码为:

class Entropy:def __init__(self, n_classes):self.n_classes = n_classesself.grad = Nonedef forward(self, x, y):# x: (b, c), y: (b)b = y.shape[0]one_hot_y = np.zeros((b, self.n_classes))one_hot_y[range(len(y)), y] = 1self.grad = one_hot_y * -1 / xreturn np.mean(-one_hot_y * np.log(x), axis=0)def backward(self):return self.grad

2. 单独的Softmax层

from einops import repeat, rearrange, einsum
class Softmax:def __init__(self):def forward(self, x):# x: (b, c)x_exp = np.exp(x)self.output = x_xep / np.sum(x_exp, axis=1, keep_dims=True)return self.outputdef backward(self, prev_grad):b, c = self.output.shapeo = repeat(self.output, 'b c -> b c r', r=c)I = repeat(np.eye(x.shape[1]), 'c1 c2 -> b c1 c2', b=b)self.grad = o * (I - rearrange(o, 'b c1 c2 -> b c2 c1'))return einsum(self.grad, grad[..., None], 'b c c, b c m -> b c m')[..., 0]		

3. Linear层

注意更新 w w w时用的 d w d_w dw, 但是往上一层传递的是 d x d_x dx。因为上一层需要 d L / d o u t dL/d_{out} dL/dout, 而本层的输入 x x x即是上一次层的输出 d L / d o u t = d L / d x dL/d_{out} = dL/dx dL/dout=dL/dx

class Linear:def __init__(self, in_channels, out_channels, lr):self.lr = lrself.w = np.random.rand(in_channels, out_channels)self.b = np.random.rand(out_channels)def forward(self, x):self.x = xreturn x@self.w + self.bdef backward(self, grad):dx = einsum(prev_grad, rearrange(self.w, 'w1 w2 -> w2 w1'), 'c1 b, b c2 -> c1 c2')dw = einsum(rearrange(self.x, 'b c -> c b'), prev_grad, 'c1 b, b c2 -> c1 c2')db = np.sum(prev_grad, axis=0)self.w -= self.lr * dwself.b -= self.lr * db"""注意这里往上一层传递的是dx, 因为上一层需要dL/d_out, 而本层的输入x即是上一次层的输出dL/d_out = dL/dx"""return dx

5. 完整训练代码

from einops import *
import numpy as npclass Softmax:def __init__(self, train=True):self.grad = Noneself.train = traindef forward(self, x, y):prob = np.exp(x-np.max(x, axis=1, keepdims=True))prob /= np.sum(prob, axis=1, keepdims=True)if self.train:loss = -np.sum(np.log(prob[range(len(y)), y]))/len(y)self.grad = prob.copy()self.grad[range(len(y)), y] -= 1self.grad /= len(y)return prob, losselse:return probdef backward(self):return self.gradclass Linear:def __init__(self, in_channels, out_channels, lr):self.w = np.random.rand(in_channels, out_channels)self.b = np.random.rand(out_channels)self.lr = lrdef forward(self, x):self.x = xoutput = einsum(x, self.w, 'b c1, c1 c2 -> b c2') + self.breturn outputdef backward(self, prev_grad):cur_grad = einsum(rearrange(self.x, 'b c -> c b'), prev_grad, 'c1 b, b c2 -> c1 c2')self.w -= self.lr * cur_gradself.b -= self.lr * np.sum(prev_grad, axis=0)return cur_gradclass Network:def __init__(self, in_channels, out_channels, n_classes, lr):self.lr = lrself.linear = Linear(in_channels, out_channels, lr)self.softmax = Softmax()def forward(self, x, y=None):out = self.linear.forward(x)out = self.softmax.forward(out, y)return outdef backward(self):grad = self.softmax.backward()grad = self.linear.backward(grad)return gradif __name__ == "__main__":data = np.array([[2, 1, 0],[2, 2, 0],[5, 4, 1],[4, 5, 1],[2, 3, 0],[3, 2, 0],[6, 5, 1],[4, 1, 0],[6, 3, 1],[7, 4, 1]])# x = np.concatenate([np.array([[1]] * data.shape[0]), data[:, :2]], axis=1)x = data[:, :-1]y = data[:, -1:].flatten()net = Network(2, 2, 2, 0.1)# loss_fn = CrossEntropy(n_classes=2)for epoch in range(500):prob, loss = net.forward(x, y)# loss = loss_fn.forward(out, y)# grad_ = loss_fn.backward()grad = net.backward()print(loss)net.softmax.train = Falseprint(net.forward(np.array([[0, 0], [0, 4], [8, 6], [10, 10]])), y)

相关文章:

一步一步用numpy实现神经网络各种层

1. 首先准备一下数据 if __name__ "__main__":data np.array([[2, 1, 0],[2, 2, 0],[5, 4, 1],[4, 5, 1],[2, 3, 0],[3, 2, 0],[6, 5, 1],[4, 1, 0],[6, 3, 1],[7, 4, 1]])x data[:, :-1]y data[:, -1]for epoch in range(1000):...2. 实现SoftmaxCrossEntropy层…...

vue学习(二)

9.vue中的数据代理 通过vm对象来代理data对象中的属性操作(读写),目的是为了更加方便操作data中的数据 基本原理:通过Object.defineProperty()把data对象所有属性添加到vm上,为每一个添加到vm上的属性,都增…...

Maven 介绍

Maven open in new window 官方文档是这样介绍的 Maven 的: Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a projects build, reporting and documentation fr…...

QT截图程序三-截取自定义多边形

上一篇文章QT截图程序,可多屏幕截图二,增加调整截图区域功能-CSDN博客描述了如何截取,具备调整边缘功能后已经方便使用了,但是与系统自带的程序相比,似乎没有什么特别,只能截取矩形区域。 如果可以按照自己…...

Unity的三种Update方法

1、FixedUpdate 物理作用——处理物理引擎相关的计算和刚体的移动 (1) 调用时机:在固定的时间间隔内,而不是每一帧被调用 (2) 作用:用于处理物理引擎的计算,例如刚体的移动和碰撞检测 (3) 特点:能更准确地处理物理…...

[Python学习篇] Python字典

字典是一种可变的、无序的键值对(key-value)集合。字典在许多编程(Java中的HashMap)任务中非常有用,因为它们允许快速查找、添加和删除元素。字典使用花括号 {} 表示。字典是可变类型。 语法: 变量 {key1…...

react项目中如何书写css

一:问题: 在 vue 项目中,我们书写css的方式很简单,就是在 .vue文件中写style标签,然后加上scope属性,就可以隔离当前组件的样式,但是在react中,是没有这个东西的,如果直…...

PostgreSQL源码分析——绑定变量

这里分析一下函数中应用绑定变量的问题,但实际应用场景中,不推荐这么使用。 prepare divplan2(int,int) as select div($1,$2); execute divplan2(4,2);语法解析 分别分析prepare语句以及execute语句。 gram.y中定义 /******************************…...

Zynq学习笔记--了解中断配置方式

目录 1. 简介 2. 工程与代码解析 2.1 Vivado 工程 2.2 Vitis 裸机代码 2.3 关键代码解析 3. 总结 1. 简介 Zynq 中的中断可以分为以下几种类型: 软件中断(Software Generated Interrupt, SGI):由软件触发,通常…...

吴恩达机器学习 第二课 week2 多分类问题

目录 01 学习目标 02 实现工具 03 概念与原理 04 应用示例 05 总结 01 学习目标 (1)理解二分类与多分类的原理区别 (2)掌握简单多分类问题的神经网络实现方法 (3)理解多分类问题算法中的激活函数与损失…...

112、路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。 叶子节点 是指没有子节点…...

Vue 封装组件之Input框

封装Input组件:MyInput.vue <template><div class"base-input-wraper"><el-inputv-bind"$attrs"v-on"$listeners"class"e-input":style"inputStyle":value"value":size"size"input&quo…...

一段代码让你了解Java中的抽象

我们先来看一道题&#xff01; 计算几何对象的面积之和&#xff09;编写一个方法&#xff0c;该方法用于计算数组中所有几何对象的面积之和。该方法的签名是&#xff1a; public static double sumArea(GeometricObject[] a) 编写一个测试程序&#xff0c;该程序创建一个包含四…...

Sping源码(九)—— Bean的初始化(非懒加载)— Bean的创建方式(factoryMethod)

序言 前面文章介绍了在Spring中多种创建Bean实例的方式&#xff0c;包括采用FactoryBean的方式创建对象、使用反射创建对象、自定义BeanFactoryPostProcessor。 这篇文章继续介绍Spring中创建Bean的形式之一——factoryMethod。方法用的不多&#xff0c;感兴趣可以当扩展了解。…...

绝对全网首发,利用Disruptor EventHandler实现在多线程下顺序执行任务

disruptor有两种任务处理器&#xff0c;一个是EventHandler ,另一个是WorkHandler. EventHandler可以彼此独立消费同一个队列中的任务&#xff0c;WorkHandler可以共同竞争消费同一个队列中的任务。也就是说&#xff0c;假设任务队列中有a、b、c、d三个事件&#xff0c;eventHa…...

单例设计模式双重检查的作用

先看双重校验锁的写法 public class Singleton {/*volatile 修饰&#xff0c;singleton new Singleton() 可以拆解为3步&#xff1a;1、分配对象内存(给singleton分配内存)2、调用构造器方法&#xff0c;执行初始化&#xff08;调用 Singleton 的构造函数来初始化成员变量&am…...

NGINX_十二 nginx 地址重写 rewrite

十二 nginx 地址重写 rewrite 1 什么是Rewrite Rewrite对称URL Rewrite&#xff0c;即URL重写&#xff0c;就是把传入Web的请求重定向到其他URL的过程。URL Rewrite最常见的应用是URL伪静态化&#xff0c;是将动态页面显示为静态页面方式的一种技术。比如 http://www.123.com…...

react用ECharts实现组织架构图

找到ECharts中路径图。 然后开始爆改。 <div id{org- name} style{{ width: 100%, height: 650, display: flex, justifyContent: center }}></div> // data的数据格式 interface ChartData {name: string;value: number;children: ChartData[]; } const treeDep…...

坚持刷题|合并有序链表

文章目录 题目思考代码实现迭代递归 扩展实现k个有序链表合并方法一方法二 PriorityQueue基本操作Java示例注意事项 Hello&#xff0c;大家好&#xff0c;我是阿月。坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;消失了一段时间&#xff0c;我又回来刷题啦&#xff0c;今天…...

SPI协议——对外部SPI Flash操作

目录 1. W25Q32JVSSIQ背景知识 1.1 64个可擦除块 1.2 1024个扇区&#xff08;每个块有16个扇区&#xff09; 1.3 页 1. W25Q32JVSSIQ背景知识 W25Q32JV阵列被组织成16,384个可编程页&#xff0c;每页有256字节。一次最多可以编程256个字节。页面可分为16组(4KB扇区清除&…...

kotlin类型检测与类型转换

一、is与!is操作符 1、使用 is 操作符或其否定形式 !is 在运行时检测对象是否符合给定类型。 fun main() {var a "1"if(a is String) {println("a是字符串类型:${a.length}")}// 或val b a is Stringprintln(b) } 二、"不安全的"转换操作符…...

【JDBC】Oracle数据库连接问题记录

Failed to load driver class oracle.jdbc.driver.OracleDriver in either of HikariConfig class oracle驱动包未正确加载&#xff0c;可以先尝试使用下面方式加载检查类是否存在&#xff0c;如果不存在需要手动下载odbc包 try {Class.forName("oracle.jdbc.driver.Ora…...

leetcode45 跳跃游戏II

题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到达 nums[n - 1]…...

【数学】什么是方法矩估计?和最大似然估计是什么关系?

背景 方法矩估计&#xff08;Method of Moments Estimation&#xff09;和最大似然估计&#xff08;Maximum Likelihood Estimation, MLE&#xff09;是两种常用的参数估计方法。方法矩估计基于样本矩与总体矩的关系&#xff0c;通过样本数据计算样本矩来估计总体参数。最大似…...

C++初学者指南第一步---10.内存(基础)

C初学者指南第一步—10.内存&#xff08;基础&#xff09; 文章目录 C初学者指南第一步---10.内存&#xff08;基础&#xff09;1.内存模型1.1 纸上谈兵&#xff1a;C的抽象内存模型1.2 实践&#xff1a;内存的实际处理 2. 自动存储3.动态存储&#xff1a;std::vector3.1 动态内…...

扩散模型详细推导过程——编码与解码

符号表 符号含义 x ( i ) z 0 ( i ) \boldsymbol{x}^{(i)}\boldsymbol{z}_0^{(i)} x(i)z0(i)​第 i i i个训练数据&#xff0c;其为长度为 d d d的向量 z t ( i ) \boldsymbol{z}_t^{(i)} zt(i)​第 i i i个训练数据在第 t t t时刻的加噪版本 ϵ t ( i ) \boldsymbol{\epsilo…...

js如何实现开屏弹窗

开屏弹窗是什么&#xff0c;其实就是第一次登录后进入页面给你的一种公告提示&#xff0c;此后再回到当前这个页面时弹窗是不会再出现的。也就是说这个弹窗只会出现一次。 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>…...

C#——文件读取Directory类详情

文件读取Directory类 Durectory提供了目录以及子目录进行创建移动和列举操作方法 Directory和Directorylnfo类(主要操作文件目录属性列如文件是否隐藏的 或者只读等这些属性) Directory对目录进行复制、移动、重命名、创建和删除等操作DirectoryInfo用于对目录属性执行操作 …...

Ruby on Rails Post项目设置网站初始界面

在构建了Ruby的Web服务器后&#xff0c;第三步就可以去掉框架的官方页面&#xff0c;设置自己的网页初始页了。 Linux系统安装Ruby语言-CSDN博客 、在Ubuntu中创建Ruby on Rails项目并搭建数据库-CSDN博客、 Ruby语言建立Web服务器-CSDN博客 了解Ruby onRails项目中的主要文件…...

03-QTWebEngine中使用qtvirtualkeyboard

qt提供了 virtualKeyboard 虚拟键盘模块&#xff0c;只需要在在main函数中最开始加入这样一句就可以了 qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); 但是在使用的时候遇到了一些问题&#xff1a; 1、中文输入的时候没有输入提示 Qvirt…...

最新台湾消息台湾新闻/什么叫做优化

Nginx1.8.0安装手册 一、预备环境 nginx是C语言开发&#xff0c;建议在linux上运行&#xff0c;本教程使用Centos6.8作为安装环境。 1. gcc 安装nginx需要先将官网下载的源码进行编译&#xff0c;编译依赖gcc环境&#xff0c;如果没有gcc环境&#xff0c;需要安装gcc&#xf…...

做电销哪些网站可以找到客户端/中国搜索引擎市场份额

php与数据库之间的链接&#xff0c;用数据库里的数据 将数据库的数据添加到HTML语句中转载于:https://www.cnblogs.com/huzhen/p/3712880.html...

javaweb可以做网站吗/品牌营销策划方案怎么做

1、打开激活窗口 2、选择 Activate new license with License server &#xff08;用license server 激活&#xff09; 3、在 License sever address 处填入 https://jetlicense.nss.im/ 4、点击 Activate 进行认证 还有一种方法比较麻烦&#xff0c;就不提及了...

人才网网站开发手册/如何制作自己的网址

微软小娜&#xff08;Cortana&#xff09; ios版 第一部分&#xff1a;测评 1、首次体验 界面内容很多&#xff0c;地图 新闻 美食 电影 天气等 连车辆限号都有&#xff0c;感觉很强大。视觉上感觉很舒适&#xff0c;背景颜色也有多种颜色可供选择。功能也很多&#xff0c;提醒…...

济南哪个公司做网站好/百度平台营销收费标准

特定类型查询优化 优化COUNT()查询 COUNT()可能是被大家误解最多的函数了&#xff0c;它有两种不同的作用&#xff0c;其一是统计某个列值的数量&#xff0c;其二是统计行数。统计列值时&#xff0c;要求列值是非空的&#xff0c;它不会统计NULL。如果确认括号中的表达式不可…...

wordpress微信扫码登录/建设网站制作公司

网页基本元素-按钮打造 按钮分类 平面类、体积类、光感类、凹面类按钮特点 有区别于背景的外框有对应的文字/图标按钮的本质特点就是可以点击 按钮规范 按钮大小根据文字大小确定&#xff0c;文字大小一般为18~24px文字大小一般为按钮高度的一半&#xff0c;左右边距大于上…...