最近接触了一个C++神经网络库 cnn,但由于对C++用的不多,首先还是从它的python版本pycnn入手。
本篇翻译和整理了pycnn的使用方法,cnn及pycnn的安装见 cnn安装。
使用pycnn,第一步当然是引入pycnn库,很简单:
from pycnn import *
cnn里面有一个叫做Computation Graph的概念,它定义了神经网络的信息流,在C++版本中需要首先创建,但在python版本里它是一个单例,引入库时就已经有了。而我们需要做的仅仅是更新一下,目的是清除当前的状态并开始一个新的:
renew_cg()
神经网络一定会有输入数据,数据的类型可能是标量,向量或是矩阵,因此首先定义一个接收数据的表达式叫做Expression:
x = scalarInput(value) #顾名思义,接收一个标量
v = vecInput(dimension) #接收一个指定长度的向量
z = matInput(d1, d2) #接收一个指定大小的矩阵
举个例子吧,定义一个2*2大小的矩阵,并赋值:
z = matInput(2, 2) #定义矩阵z
z.set([1, 2, 3, 4]) #传入数据
然后我们就可以获取表达式的值(对于复杂的表达式,将会执行正向传播,之后会讲到):
print z.npvalue() #输出为numpy中的数组array
print v.vec_value() #输出向量v的值
print x.scalar_value() #输出标量x的值
print z.value() #会选择正确的一种输出
参数就是我们在神经网络中训练调试的,通常来说是一个矩阵或向量。
首先,我们创建一个模型,然后给模型添加参数:
m = Model()
pW = m.add_parameters('W', (8, 8)) # 添加一个8*8的矩阵参数
pb = m.add_parameters('b', 8) # 一个8*1的列向量
然后我们创建一个表达式Expression对应模型中的参数:
W = parameter(pW) # or W = parameter(m['W'])
b = parameter(pb)
Lookup parameters类似于parameters,但是它表示一个查找表“lookup table”,将数字映射成向量,用于向量矩阵(embedding matrices),例如有VOCAB_SIZE行,每行的维度是DIM:
lp = m.add_lookup_parameters('lookup', (VOCAB_SIZE, DIM))
它也可以通过一个已存在的数组初始化,例如:
m['lookup'].init_from_array(wv)
下面是一些操作:
e5 = lookup(lp, 5) # 从第5行创建一个表达式
e5c = lookup(lp, 5, update=False) # 同上,只是优化的时候不更新
e5.set(9) # 现在这个表达式e5包含了第9行
#数学
e = e1 + e2
e = e1 * e2 # 对于向量和矩阵来说是点乘,相当于numpy中的e1.dot(e2)
e = e1 - e2
e = -e1
e = dot_product(e1, e2)
e = cwise_multiply(e1, e2) # component-wise divide (like e1*e2 in numpy)
e = cdiv(d1, e2) # component-wise divide
e = colwise_add(e1, e2) # column-wise addition
#矩阵形状
e = reshape(e1, news_dimension)
e = transpose(e1)
#每个元素的一元运算
e = tanh(e1)
e = exp(e1)
e = log(e1)
e = logistic(e1) # Sigmoid(x)
e = rectify(e1) # Relu (= max(x,0))
e = softsign(e1) # x/(1+|x|)
#softmax
e = softmax(e1)
e = log_softmax(e1, restrict=[]) # restrict is a set of indices. if not empty, only entries in restrict are part of softmax computation, others get 0.
e = sum_cols(e1)
#从向量表达式中选取元素值
e = pick(e1, k)
e = e1[k] # 这两者相同
e = pickrange(e1, k, v)
e = e1[k:v] # 这两者相同,返回向量第k到v之间的元素值
e = pickneglogsoftmax(e1, k) # 等同于pick(-log(softmax(e1)), k)
#Neural net stuff
##不清楚怎么翻译,直接复制原标题
noise(e1, stddev) # 对每个元素加上一个标准差为stddev的高斯函数值的噪声
dropout(e1, p) # 以概率p进行dropout,防止过拟合
#对表达式列表的操作
e = esum([e1, e2, ...])
e = average([e1, e2, ...])
e = concatenate_cols([e1, e2, ...]) # e1,e2都是列向量,返回一个矩阵
e = concatenate([e1, e2, ...])
e = affine_transfoem([e0, e1, e2, ...]) # e = e0 + (e1*e2+e3*e4+ ...)
e = squared_distance(e1, e2)
e = l1_distance(e1, e2)
e = huber_distance(e1, e2, c=1.345)
e = binary_log_loss(e1, e2) # e1和e2必须是0到1之间的标量
# e = e2*log(e1) + (1-e2)*log(e1)
e = pairwise_rank_loss(e1, e2, m=1.0) # e1和e2是行向量或者标量,e = max(0, m-(e1-e2))
#Convolutions 卷积
e = conv1d_narrow(e1, e2)
e = conv1d_wide(e1, e2)
e = kmax_pooling(e1, k)
e = kmh_ngram(e1, k)
e = fold_rows(e1, nrows=2)