ESIM 网络的搭建和训练

一、前言 最近半年多的时间里学了许多人工智能,尤其是深度学习的知识,但是一直没有搭建过一个较为复杂的神经网络,最多也只是一个简单的 rnn。这主要是因为自己的笔记本没有训练较大模型的能力。 因为对nlp比较感兴趣,因此最近开始尝试跟着复旦大学邱锡鹏老师的NLP入门练习搭建网络。但到任务三时自己的笔记本就无法继续训练了,于是这次我下定决心找到训练一个比较好的训练模型的方法。最终找到了 Colab。 因为使用了Colab,本次模型的构建和训练比较成功,因而做此记录。 二、任务 本次任务是输入两个句子,判断它们之间的关系。具体来说,我们需要实现论文中提出的 ESIM 网络,并通过 SNLI数据集 进行训练,以学习预测两个句子间的关系。 三、数据集 SNLI数据集包含57万行英文句子对,并被标注了句子间的关系,包括蕴含(Entailment),矛盾(Contradiction),中立/不冲突(Neutral),未知(-)。 例如 输入文本: A man inspects the uniform of a figure in some East Asian country. 输入假设: The man is sleeping. 输出: 矛盾(C) 输入文本: A smiling costumed woman is holding an umbrella. 输入假设:A happy woman in a fairy costume holds an umbrella. 输出: 中立(N) 输入文本: A soccer game with multiple males playing. 输入假设: Some men are playing a sport....

三月 5, 2023 · 4 分钟 · 755 字 · Wokron

利用 Colab 训练神经网络

一、算力从哪里来? 曾听到过这样一种说法,深度学习 “自学 + 没经费 = 天坑”。不幸的是我似乎正处于这种状态中。自学的方面还比较好克服,可没有 gpu 进行训练就 “难为无米之炊” 了。就算理论学得再好,自己构建的模型电脑带不动,没有实践的机会,也是难以学好这门学科的。 最近我正开始学着实现更大的模型,我的笔记本此前的小模型还可以勉强撑住,可现在却完全带不动了。一方面,训练的时间太长,挤占了我使用笔记本做其他事的时间;另一方面,我的 gpu 显存太小,不能调大参数,可参数较小时又无法收敛。这就是我面临的双重两难问题。 我希望找到一处租用算力的平台。它应该同时满足如下的条件 算力丰富,能快速训练模型 对用户友好,和本机环境差别不大,能够迅速上手训练模型 费用便宜,最好有免费的算力 综合以上各点,通过搜索,我找到了 Colab。Colab(oratory) 是一个 Google 研究项目,旨在帮助传播机器学习培训和研究成果。它是一个 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行。Colab 笔记本存储在 Google 云端硬盘中,并且可以共享。利用Colaboratory ,可以方便的使用Keras, TensorFlow, PyTorch, OpenCV 等框架进行深度学习应用的开发。最重要的是,Colab 可免费使用。 二、Colab基本操作 (1)创建笔记本 在正式介绍 Colab 之前需要说明一点,使用 Colab 需要科学上网。 要新建 Colab 需要创建笔记,笔记是 Colab 编辑文本、代码和运行程序的地方。使用过 jupyter notebook 的人应该很了解。不同笔记之间内容互不相通,可以把每一个笔记看做一台独立运行的虚拟机。 Colab 是谷歌的产品,因此需要实现注册好一个谷歌账号。 通过 Google Drive 创建笔记本 Google Drive 是 Google 的一款云端硬盘,操作与其他云盘,如百度网盘、阿里云盘,类似。 通过 Google Drive 可以创建 Colab 笔记。方式是:点击左上角的“新建”按钮或右击背景 => 在弹出的窗口中选择“更多” => 选择 “Google Colaboratory” 选项。...

三月 4, 2023 · 2 分钟 · 267 字 · Wokron

利用 ASM 库实现 Java 反射

一、ASM库简介 ASM 库是一款基于 Java 字节码层面的代码分析和修改工具。它能分析二进制的 class 文件并对其进行动态修改。ASM 库侧重性能,设计和实现尽可能小和快。 通过 ASM 库,我们可以方便地获取类信息,并实现类似于反射的功能。ASM 库处理字节码,因此能得到仅仅使用反射无法获取的信息,如方法内的结构。 ASM 库同样具有动态修改和创建类文件的功能,但本篇文章主要使用 ASM 库的字节码读取功能。 本篇文章假设读者能自行通过Maven或其他方式添加ASM库依赖。 二、利用ASM库访问类文件 ASM 库的核心库提供了读取和修改字节码的基本 API。核心库包含如下几个工具类: ClassReader ClassReader 类用于从 class 文件中加载字节码。这样,这一 ClassReader 对象就拥有了关于某一类的所有信息。 ClassVisitor ClassVisitor 类可以从 ClassReader 中获取想要的信息。 ClassVisitor 是访问者模式的访问类。简单解释访问者模式,就是被访问的对象调用访问者类的方法,从而使得访问者获取希望得到的数据。 还是通过 ASM 的例子来理解吧,ClassVisitor 实际是一个抽象类,其中定义了一个方法 visit。该方法的签名为: visit(int version, int access, String name, String signature, String superName, String[] interfaces) 假设我们继承 ClassVisitor 创建了一个新的访问类,那么获取信息的方式如下: ClassReader cr = new ClassReader("className"); ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { // this is an anonymous class }; cr....

二月 21, 2023 · 3 分钟 · 442 字 · Wokron

Java 注解与 C# 特性

一、元数据简介 元数据是指用来描述数据的数据。对编程语言来说,元数据可以为程序中元素添加额外的信息。这一功能可以被用于描述代码间关系,以及代码与其他资源的联系。 元数据可以被用于框架中。通过元数据可以实现在代码上对类的直接配置,避免编写如 xml 的配置文件。 Java 和 C# 都具有为程序中元素,如类、方法等等,添加元数据的方式。Java中称为注解,而C#中称为特性。注解和特性都通过反射获取,关于两者的获取方式,已经在前一篇文章中有所记述。本篇只讨论注解和特性的定义和使用。 二、Java注解 注解的定义 如果想要自定义注解,需要继承 Annotation 类。 public class MyAnnotation extends Annotation { } 同时还有另一种写法,由此可知注释本质上是接口 public @interface MyAnnotation2 { } 和接口一样,注解可以添加静态变量 我们可以为注解添加“参数”,比如 Spring 中的注解 @Profile(value = "dev")。我们为其设置了 value 属性。 但是注解本是接口,不可能有保存数据的能力,要如何设置注解的属性呢?实际上,注解的属性在编写 Annotation 时是一个方法。即 public @interface MyProfile { String value(); } 还可以为参数添加默认值 public @interface MyAnnotation3 { String value(); int number() default 8; // set default number } 注解经常和枚举一起使用。 public @interface MyAnnotation4 { enum SELECT_TYPE {TYPE_A, TYPE_B} SELECT_TYPE selectType() default TYPE_A; } 元注解 元注解是注解的元数据,也就是对注解的注解。元注解为注解设置额外的信息,如设置注解的作用对象等等。...

二月 20, 2023 · 1 分钟 · 196 字 · Wokron

Java 和 C# 中的反射机制

一、反射简介 反射是一种程序动态访问修改其状态或行为的机制。具体来说,反射提供了在程序运行时对代码进行操作的手段。 反射提高了程序的灵活性和扩展性,能使程序员通过字符串动态地实现程序的修改。它降低了代码间的耦合度,可以避免硬编码,实现代码的组件化。反射的这些特点在对灵活性和扩展性要求很高的框架上有巨大的作用。 当然,也需要注意到,反射通过字符串进行操作的方式是解释性的,这将导致性能的降低。 二、反射的原理 对于拥有虚拟机(或者类似的东西,虚拟机只是一个不正规的名词)的语言,都存在加载字节码(同样不正规的名词)到虚拟机的过程。在这个过程中,虚拟机获取了有关类的信息,包括继承关系、包含的字段和方法等等。对于java来说,局部变量放在栈中,类实例放在堆中,程序方法放在方法区中。 对不使用反射的一般情况来说,方法调用更加直接。调用时虚拟机将根据编译时即确定的方法地址进行跳转。而对于反射,则需要根据字符串查找对应的类或方法。这样查找而非硬编码的过程就会影响性能。 二、java中的反射 通过反射我们能获取java语言中的如下组成部分:包、类(和接口)、方法(一般/构造)、字段、注解。反射不能操作方法中的内容。 类是面向对象的基本单元,我们通过获取类来实现对程序的动态操作。 (1)类和包 “类” Class<?> 是一个用于表示类的类型。它有三种获取方式 ClassName.class // 类型名.class obj.getClass(); // 对象.getClass Class.forName(String className); // Class.forName("包含包路径的类型全称") 前两种较好理解,相当于获取一个类型,我们可以用这编写一个类似于 instanceof 的函数。 boolean typeof(Object obj, Class<?> cls) { return obj.getClass() == cls; } 当然这无法将子类也判断为真。值得注意的是这里我们直接使用了 == 而不是 equals。因为对于每一个类,Class只用一个实例。 但第三种才最为重要,它通过字符串获取了一个类型。这就为程序提供了灵活性。 获取了一个 Class 对象后,我们可以进一步获取其父类和实现的接口 Class<?> cls = Class.forName("somepackages.someClass"); Class<?> superCls = cls.getSuperclass(); Class<?>[] interfaces = cls.getInterfaces(); 值得注意的是获取接口方法返回的是一个 Class 数组。这说明对于虚拟机来说本没有类和接口之分。 调用 getPackage 可以获取包 Package p = cls.getPackage(); Package 类型保存了该包的一些信息,如名称、版本等等,不一一列举。...

二月 19, 2023 · 3 分钟 · 537 字 · Wokron

2D 物理引擎基础之刚体力学与碰撞约束

一、前言 本文是“2D物理引擎基础”的第三篇文章,主要介绍物体刚体力学的相关知识以及碰撞发生后的处理办法。后者背后的数学原理较为复杂,因此这里大多情况只是罗列公式并做简要说明。 二、刚体力学 连续的刚体力学 我们考虑二维的情况。假设有一刚体,质量为 $M$,转动惯量为 $I$,在距质心 $\vec{r}$ 处受到一力 $\vec{F}$ 的作用。 那么刚体所受相对于质心的力矩 $\vec{M}$ 为: $$ \vec{M} = \vec{r} \times \vec{F} $$ 注意 $\vec{M}$ 的方向垂直于平面,后面的角速度同理。 在 $\Delta{t}$ 时间内速度变化 $\Delta{\vec{v}}$ 有 $$ \Delta{\vec{v}} = \int_{t_0}^{t0+\Delta{t}} \frac{\vec{F}(t)}{M} dt $$ 同样的,角速度变化 $\Delta{\vec{w}}$ 有 $$ \Delta{\vec{w}} = \int_{t_0}^{t0+\Delta{t}} \frac{\vec{M(t)}}{I} dt $$ 类似的,也有位置和角度的变化 $$ \Delta{\vec{p}} = \int_{t_0}^{t0+\Delta{t}} \vec{v}(t) dt $$ $$ \Delta{\vec{\theta}} = \int_{t_0}^{t0+\Delta{t}} \vec{w}(t) dt $$ 还有冲量 $$ \vec{I} = \int_{t_0}^{t0+\Delta{t}} \vec{F}(t) dt $$ 以及角冲量(或称冲量矩) $$ \vec{H} = \int_{t_0}^{t0+\Delta{t}} \vec{M}(t) dt $$ 并有等式 $$ \vec{I} = M \Delta{\vec{v}} $$ $$ \vec{H} = I \Delta{\vec{w}} $$ 离散的刚体模拟 正如第一篇文章中说过的,一般情况下计算机无法计算连续,只能通过离散的方式进行近似。物理引擎中进行的模拟会导致误差,但这对于视觉效果来说已经足够了。...

二月 10, 2023 · 5 分钟 · 865 字 · Wokron