#用python实现RNN
#用RNN学习二进制加法:1.学习当前位的加法;2.学习关于前一位的进位
import copy,numpy as np
np.random.seed(0)
def sigmoid(inX):
return 1/(1+np.exp(-inX))
def sigmoid_output_to_derivative(output):
return output*(1-output)
int2binary={}#字典格式
binary_dim=8#二进制最多8位-即2^8
#二进制和十进制的对应
largest_number=pow(2,binary_dim )
binary = np.unpackbits(np.array([range(largest_number)],dtype=np.uint8).T,axis=1)
#unpackbits函数可以把整数转化成2进制数
for i in range(largest_number ):
int2binary[i]=binary[i]
#对网络进行初始化
alpha=0.1
input_dim=2#两个数相加
hidden_dim=16
output_dim=1
#权重值的初始化操作
synapse_0=2*np.random.random((input_dim, hidden_dim))-1
synapse_1=2*np.random.random((hidden_dim, output_dim))-1
synapse_h=2*np.random.random((hidden_dim, hidden_dim))-1
#反向传播更新的参数保存在这里
synapse_0_update=np.zeros_like(synapse_0)
synapse_1_update=np.zeros_like(synapse_1)
synapse_h_update=np.zeros_like(synapse_h)
#10000次迭代
for j in range(10000):
#a+b=c
a_int=np.random.randint(largest_number/2)
a=int2binary[a_int]
b_int = np.random.randint(largest_number / 2)
b = int2binary[b_int]
c_int=a_int+b_int
c=int2binary[c_int]#是label值
d=np.zeros_like(c)#保存预测值
overallError = 0#保存损失值
layer_2_deltas=list()
layer_1_values=list()#上一个阶段的值
layer_1_values.append(np.zeros(hidden_dim))
for position in range(binary_dim ):
x=np.array([[a[binary_dim -position-1],b[binary_dim -position-1]]])
y=np.array([[c[binary_dim -position-1]]]).T
layer_1=sigmoid(np.dot(x,synapse_0)+np.dot(layer_1_values[-1],synapse_h))#注意点
#list-表示列表list[-1]表示从右侧开始读取的第一个元素
#dot()返回的是两个数组的点积(dot product)
#如果处理的是一维数组,则得到的是两数组的內积
#如果是二维数组(矩阵)之间的运算,则得到的是矩阵积
layer_2=sigmoid(np.dot(layer_1,synapse_1 ))
layer_2_error=y-layer_2
layer_2_deltas.append((layer_2_error)*sigmoid_output_to_derivative(layer_2))#注意点
overallError += np.abs(layer_2_error[0])
d[binary_dim-position-1]=np.round(layer_2[0][0])
#函数原型是:round(flt, ndig=0) 其中 ndig 是小数点的后面几位(默认为0),然后对原浮点数 进行四舍五入的操作。
layer_1_values.append(copy.deepcopy(layer_1))
future_layer_1_delta=np.zeros(hidden_dim)#循环结构传下来的
for position in range(binary_dim):
x=np.array([[a[position],b[position]]])
layer_1=layer_1_values[-position-1]
prev_layer_1=layer_1_values[-position-2]
layer_2_delta=layer_2_deltas[-position-1]
layer_1_delta=(future_layer_1_delta.dot(synapse_h.T)+layer_2_delta .dot(synapse_1 .T))*sigmoid_output_to_derivative(layer_1)
#注意点
#参数更新
synapse_1_update +=np.atleast_2d(layer_1).T.dot(layer_2_delta)
#维度改变 :atleast_xd 支持将输入数据直接视为 x维。这里的 x 可以表示:1,2,3。
synapse_h_update +=np.atleast_2d(prev_layer_1).T.dot(layer_1_delta)
synapse_0_update +=x.T.dot(layer_1_delta)
future_layer_1_delta =layer_1_delta
synapse_0 +=synapse_0_update *alpha
synapse_1 +=synapse_1_update *alpha
synapse_h +=synapse_h_update *alpha
synapse_0_update *=0
synapse_1_update *=0
synapse_h_update *=0
if(j % 1000 == 0):
print("Error:", str(overallError))
print("Pred:", str(d))
print("True", str(c))
out = 0
for index,x in enumerate(reversed(d)):
out += x * pow(2, index)
print(str(a_int)+"+ " + str(b_int)+"="+str(out))
print("-------------------------------------")
最终结果如下:
Error: [3.45638663]
Pred: [0 0 0 0 0 0 0 1]
True [0 1 0 0 0 1 0 1]
9+ 60=1
Error: [3.63389116]
Pred: [1 1 1 1 1 1 1 1]
True [0 0 1 1 1 1 1 1]
28+ 35=255
Error: [3.91366595]
Pred: [0 1 0 0 1 0 0 0]
True [1 0 1 0 0 0 0 0]
116+ 44=72
Error: [3.72191702]
Pred: [1 1 0 1 1 1 1 1]
True [0 1 0 0 1 1 0 1]
4+ 73=223
Error: [3.5852713]
Pred: [0 0 0 0 1 0 0 0]
True [0 1 0 1 0 0 1 0]
71+ 11=8
Error: [2.53352328]
Pred: [1 0 1 0 0 0 1 0]
True [1 1 0 0 0 0 1 0]
81+ 113=162
Error: [0.57691441]
Pred: [0 1 0 1 0 0 0 1]
True [0 1 0 1 0 0 0 1]
81+ 0=81
Error: [1.42589952]
Pred: [1 0 0 0 0 0 0 1]
True [1 0 0 0 0 0 0 1]
4+ 125=129
Error: [0.47477457]
Pred: [0 0 1 1 1 0 0 0]
True [0 0 1 1 1 0 0 0]
39+ 17=56
Error: [0.21595037]
Pred: [0 0 0 0 1 1 1 0]
True [0 0 0 0 1 1 1 0]
11+ 3=14