开篇记录面试第28天

今天早上早起去面试了易道博识,结果因为昨晚跑步,睡得晚,早上差点起不来。


正题。记录下今天面试几个没有答出来的问题:

  1. BiLSTM里面的双向怎么解释?从概率论的角度描述一下CRF层的作用。
  2. GPU并行的软件层面的解释,比如什么时候加载,如何能实现加速?
  3. 线程和进程有什么区别?
  4. python如何实现可变长参数,有什么通用的方法
  5. set和list的区别是什么,set可以赋值吗?
    思路与解读:
    1.模型的第二层是双向LSTM层,自动提取句子特征。将一个句子的各个字的char embedding序列 (x1,x2,...,xn) 作为双向LSTM各个时间步的输入,再将正向LSTM输出的隐状态序列 (h1⟶,h2⟶,...,hn⟶) 与反向LSTM的 (h1⟵,h2⟵,...,hn⟵) 在各个位置输出的隐状态进行按位置拼接 ht=[ht⟶;ht⟵]∈ℝm ,得到完整的隐状态序列。
    image.png

    模型的第三层是CRF层,进行句子级的序列标注。CRF层的参数是一个 (k+2)×(k+2) 的矩阵 A ,Aij 表示的是从第 i 个标签到第 j 个标签的转移得分,进而在为一个位置进行标注的时候可以利用此前已经标注过的标签,之所以要加2是因为要为句子首部添加一个起始状态以及为句子尾部添加一个终止状态。
    可以看出整个序列的打分等于各个位置的打分之和,而每个位置的打分由两部分得到,一部分是由LSTM输出的 pi 决定,另一部分则由CRF的转移矩阵 A 决定。进而可以利用Softmax得到归一化后的概率。具体的公式见https://www.cnblogs.com/Determined22/p/7238342.html

2.GPU适合大规模的矩阵计算是由于它的结构,而CPU就适合复杂的逻辑计算,GPU不适合。另外从软件层面呢,介绍一个CUDA吧。
从CUDA体系结构的组成来说,包含了三个部分:开发库、运行期环境和驱动。
开发库是基于CUDA技术所提供的应用开发库。CUDA的1.1版提供了两个标准的数学运算库——CUFFT(离散快速傅立叶变换)和CUBLAS(离散基本线性计算)的实现。这两个数学运算库所解决的是典型的大规模的并行计算问题,也是在密集数据计算中非常常见的计算类型。开发人员在开发库的基础上可以快速、方便的建立起自己的计算应用。此外,开发人员也可以在CUDA的技术基础上实现出更多的开发库。
运行期环境提供了应用开发接口和运行期组件,包括基本数据类型的定义和各类计算、类型转换、内存管理、设备访问和执行调度等函数。基于CUDA开发的程序代码在实际执行中分为两种,一种是运行在CPU上的宿主代码(Host Code),一种是运行在GPU上的设备代码(Device Code)。不同类型的代码由于其运行的物理位置不同,能够访问到的资源不同,因此对应的运行期组件也分为公共组件、宿主组件和设备组件三个部分,基本上囊括了所有在GPGPU开发中所需要的功能和能够使用到的资源接口,开发人员可以通过运行期环境的编程接口实现各种类型的计算。

3.一个程序至少有一个进程,一个进程至少有一个线程. 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

4.参数以一个*号开头的代表着一个任意长度的元组(tuple),可以接收连续一串参数,比如foo('a',2,'c',5)。
参数以两个*号开头的代表着一个字典,参数的形式是“key=value”,接受连续任意多个参数。比如foo(1,4,'a'=1,'g'=c)

5.Python中的List是有序的,所以要访问List的话显然要通过序号来访问,就像是数组的下标一样。
Python中的set是集合,无序,元素只出现一次, 自动去重。add增加元素,update也可以添加元素,且参数可以是列表,元组,字典等。remove删除元素。

你可能感兴趣的:(开篇记录面试第28天)