人工智能学习笔记-Theano介绍及简单应用
Theano介绍和安装
1 什么是Theano2 Theano的特点3 安装 简单应用
1 张量
11 什么是张量12 怎么定义张量13 关于张量的精度问题 2 简单运算 实现一个神经网络
1 实现网络2 训练并测试网络 参考阅读
1 Theano介绍和安装
1.1 什么是Theano
Theano是一个较为老牌和稳定的机器学习python库之一。Theano基于Python擅长处理多维数组(紧密集成了Numpy),属于比较底层的框架,theano起初也是为了深度学习中大规模人工神经网络算法的运算所设计,我们可利用符号化式语言定义想要的结果,接着theano会对我们的程序进行编译,使其高效运行于GPU或CPU
1.2 Theano的特点
从Theano官方文档上摘抄来的对Theano的特征介绍:
tight integration with Numpy (紧密集成Numpy) —— 在Theano编译函数中使用numpy.ndarraytransparent use of a GPU (GPU的透明使用) —— 使得其对浮点数的运输非常高速efficient symbolic differentiation (高效的符号分解) —— 也是Theano的发明初衷之一,可帮我们推导我们所定义的一个或多个输入的函数speed and stability optimizations (快速且稳定的优化) —— 在函数表达式
log(1+x)
中即使
x
非常小,也可以给出精确的答案dynamic C code generation (动态生成C代码) —— 使得表达式求值(evaluate expression)更加快速extensive unit-testing and self-verification (大量的单元测试及自我验证) —— 可检测及诊断许多类型的错误
1.3 安装
系统ubuntu14.04
# 1. 先使用apt-get update命令进行更新,避免安装Python库时出现问题
$ sudo apt-get update
# 2. 接着安装在安装theano前需安装的Python库
$ sudo apt-get install python-numpy python-scipy python-matplotlib python-dev python-pip python-nose python-tk g++ libopenblas-dev git
# 3. 接着第三步便是使用pip命令安装theano
$ sudo pip install theano
2 简单应用
2.1 张量
2.1.1 什么是张量
Tensor(张量)是什么,刚开始看的时候被绕的迷迷糊糊的头都晕了,最后发现其实就是多维数组起了个高大上的名字,让人看起来很牛逼,张量向量啥的比一维数组二维数组听起来高端多了。 通俗的讲: scalar(标量) 0维数组 vector (向量) 1维数组 row (行向量) 2维数组,但是行数保证是1 col (列向量) 2维数组,但是列数保证是1 matrix (矩阵) 2维数组 tensor3 (三维矩阵) 3维数组 tensor4 (四位矩阵) 4维数组
2.1.2 怎么定义张量
后续所有的示例都需要按照如下代码引入包
import theano
import theano.tensor as T
from theano.tensor import *
from theano import shared
import numpy as np
Theano提供了一列预先定义好的张量类型可供使用者很方便地创造张量变量,所有的张量构造函数都接收一个 可选 的输入参数name。如以下便构造了三个以myvar为名字的 0维整型标量(scalar)变量
x = T.scalar('myvar', dtype='int32')
x = iscalar('myvar')
x = TensorType(dtype='int32', broadcastable=())('myvar')
还可以通过vector、row、col、matrix、tensor3及tensor4分别构造向量、行向量、列向量、矩阵、三维张量及四维张量。
我们还可以通过以下方式创造张量类型实例
# 创造一个双精度浮点类型的无名矩阵
x = dmatrix()
# 创造了一个双精度浮点类型的名为'x'的矩阵
x = dmatrix('x')
# 创造了一个双精度浮点类型的名为'xyz'矩阵
xyz = dmatrix('xyz')
# 构造三个无名双精度浮点类型矩阵
x, y, z = dmatrices(3)
# 构造三个分别名为'x','y','z'的double类型矩阵
x, y, z = dmatrices('x', 'y', 'z')
2.1.3 关于张量的精度问题
Constructordtypendimshapebroadcastablebscalarint80()()bvectorint81(?,)(False,)browint82(1,?)(True, False)bcolint82(?,1)(False, True)bmatrixint82(?,?)(False, False)btensor3int83(?,?,?)(False, False, False)btensor4int84(?,?,?,?)(False, False, False, False)btensor5int85(?,?,?,?,?)(False, False, False, False, False)wscalarint160()()wvectorint161(?,)(False,)wrowint162(1,?)(True, False)wcolint162(?,1)(False, True)wmatrixint162(?,?)(False, False)wtensor3int163(?,?,?)(False, False, False)wtensor4int164(?,?,?,?)(False, False, False, False)wtensor5int165(?,?,?,?,?)(False, False, False, False, False)iscalarint320()()ivectorint321(?,)(False,)irowint322(1,?)(True, False)icolint322(?,1)(False, True)imatrixint322(?,?)(False, False)itensor3int323(?,?,?)(False, False, False)itensor4int324(?,?,?,?)(False, False, False, False)itensor5int325(?,?,?,?,?)(False, False, False, False, False)lscalarint640()()lvectorint641(?,)(False,)lrowint642(1,?)(True, False)lcolint642(?,1)(False, True)lmatrixint642(?,?)(False, False)ltensor3int643(?,?,?)(False, False, False)ltensor4int644(?,?,?,?)(False, False, False, False)ltensor5int645(?,?,?,?,?)(False, False, False, False, False)dscalarfloat640()()dvectorfloat641(?,)(False,)drowfloat642(1,?)(True, False)dcolfloat642(?,1)(False, True)dmatrixfloat642(?,?)(False, False)dtensor3float643(?,?,?)(False, False, False)dtensor4float644(?,?,?,?)(False, False, False, False)dtensor5float645(?,?,?,?,?)(False, False, False, False, False)fscalarfloat320()()fvectorfloat321(?,)(False,)frowfloat322(1,?)(True, False)fcolfloat322(?,1)(False, True)fmatrixfloat322(?,?)(False, False)ftensor3float323(?,?,?)(False, False, False)ftensor4float324(?,?,?,?)(False, False, False, False)ftensor5float325(?,?,?,?,?)(False, False, False, False, False)cscalarcomplex640()()cvectorcomplex641(?,)(False,)crowcomplex642(1,?)(True, False)ccolcomplex642(?,1)(False, True)cmatrixcomplex642(?,?)(False, False)ctensor3complex643(?,?,?)(False, False, False)ctensor4complex644(?,?,?,?)(False, False, False, False)ctensor5complex645(?,?,?,?,?)(False, False, False, False, False)zscalarcomplex1280()()zvectorcomplex1281(?,)(False,)zrowcomplex1282(1,?)(True, False)zcolcomplex1282(?,1)(False, True)zmatrixcomplex1282(?,?)(False, False)ztensor3complex1283(?,?,?)(False, False, False)ztensor4complex1284(?,?,?,?)(False, False, False, False)ztensor5complex1285(?,?,?,?,?)(False, False, False, False, False)
2.2 简单运算
代码如下:
import numpy
import theano.tensor as T
from theano import function
# 1 定义两个变量,这里可以是2.1.3表中的任意精度
x = T.dscalar('x')
y = T.dscalar('y')
# 2 表达式
z = x + y
# 3 转换为python可以执行的函数
f = function([x, y], z)
执行结果如下
>>> f(2, 3)
array(5.0)
3 实现一个神经网络
3.1 实现网络
这是一个简单的神经网络,包含:输入层->隐藏层->输出层->损失函数 网络模型代码如下
#coding=utf-8
import numpy as np
import theano as th
from theano import tensor as T
from numpy import random as rng
class NetEncoder(object):
#在初始化函数中定义自编码器的参数
def __init__(self, data_x, data_y, hidden_size, actFun, outFun):
self.data_x = data_x
self.data_x = th.shared(name='data_x',
value=np.asarray(self.data_x, dtype=th.config.floatX),
borrow=True)
#print (self.data_x)
self.data_y = data_y
self.data_y = th.shared(name='data_y',
value=np.asarray(self.data_y, dtype=th.config.floatX),
borrow=True)
#print (self.data_y)
self.nIns = data_x.shape[0]
self.nFeatures = data_x.shape[1]
#隐藏层的神经元数量
self.hidden_size = hidden_size
#权值w,初始化取值范围,在一个固定范围中取均匀分布随机值
raw_w = np.asarray(np.random.normal(0,1,(1,self.hidden_size)),dtype=th.config.floatX)
self.w = th.shared(value=raw_w, name='W',borrow=True)
raw_w2 = np.asarray(np.random.normal(0,1,(self.hidden_size,1)),dtype=th.config.floatX)
self.w2 = th.shared(value=raw_w2, name='W2',borrow=True)
#print(self.w.get_value())
#print(self.w2.get_value())
#隐含层偏置向量
self.b1 = th.shared(name='b1',
value=np.zeros(shape=(1,self.hidden_size),dtype=th.config.floatX),
borrow=True)
#输出层偏置向量
self.b2 = th.shared(name='b2',
value=np.zeros(shape=(1,1), dtype=th.config.floatX),
borrow=True)
#print(self.b1.get_value())
#print(self.b2.get_value())
#激励函数
self.actFun = actFun
self.outFun = outFun
# 定义自编码器的训练函数
#
def train(self, n_epochs=100, learning_rate=0.1):
#向训练函数传递参数的变量
index = T.lscalar()
#公式内替代值的变量
x = T.dmatrix('x')
y = T.dmatrix('y')
params = [self.w, self.w2, self.b1, self.b2]
#隐藏层
if self.actFun is None :
hidden = T.dot(x,self.w)+self.b1
else:
hidden = self.actFun(T.dot(x,self.w)+self.b1)
#输出层,这里于之前演示代码不一致的是,这里没有用两个权值矩阵
#这里使用了同一个矩阵的转置矩阵
if self.outFun is None:
output = T.dot(hidden,self.w2)+self.b2
else:
output = self.outFun(T.dot(hidden,self.w2)+self.b2)
#损失函数
L = np.square(output - y)
#L = -T.sum(x*T.log(output)+(1-x)*T.log(1-output),axis=1)
loss = L.mean()
updates = []
#梯度下降
gparams = T.grad(loss, params)
for param,gparam in zip(params, gparams):
updates.append((param, param - learning_rate * gparam))
train = th.function(inputs=[index], outputs=[loss],
updates=updates,
givens={x:self.data_x[index:index+1,:],y:self.data_y[index:index+1,:]})
import time
#start_time = time.clock()
for epoch in xrange(n_epochs):
print 'Epoch:', epoch
for row in xrange(0, self.nIns):
train(row)
#end_time = time.clock()
#print "Average time per epoch=", (end_time - start_time)/n_epochs
w = self.w.get_value()
print(w)
w2 = self.w2.get_value()
print(w2)
b1 = self.b1.get_value()
print(b1)
b2 = self.b2.get_value()
print(b2)
def get_output(self, data):
#print(data)
w = self.w.get_value()
w2 = self.w2.get_value()
b1 = self.b1.get_value()
b2 = self.b2.get_value()
x = T.dvector('x')
if self.actFun is None:
hidden = T.dot(x, w)+b1
else:
hidden = self.actFun(T.dot(x, w)+b1)
output = T.dot(hidden,w2)+b2
ae_output = th.function(inputs=[x], outputs=[output])
n = data.shape[0]
testy=[]
for i in xrange(n):
testy.append(ae_output(data[i]))
return np.asarray(testy)
3.2 训练并测试网络
代码如下:
#coding=utf-8
import matplotlib.pyplot as plt
import numpy as np
from my_AE_code import NetEncoder
from theano import tensor as T
#随机生成一份数据
x_data = np.linspace(-1,1,30)[:,np.newaxis]
noise = np.random.normal(0,0.05,x_data.shape)
y_data = np.square(x_data) - 0.5 + noise
#创建网络,并训练
A = NetEncoder(x_data,y_data,10,T.nnet.softmax,None)
A.train(100)
plt.scatter(x_data, y_data)
testx = np.linspace(-1,1,100)[:,np.newaxis]
testy=A.get_output(testx)
testy = testy.reshape((100,))
testx = testx.reshape((100,))
#print(testx)
#print(testy)
plt.plot(testx,testy, c='r')
plt.show()
最终结果如图所示,蓝色的点为训练数据,红色线为训练后对模型的验证:
参考阅读
利用Theano理解深度学习——多层感知机利用Theano理解深度学习——自编码器实现深度学习算法实践——用Theano实现多层前馈网络