# 神经网络/自编码器的实现（向量化Python版本实现）

### 神经网络/自编码器的实现（向量版本）

# -*- coding: utf-8 -*-
"""
Created on Tue Jan  2 17:47:29 2018

@author: lyh
"""
import numpy as np
from sklearn.preprocessing import MinMaxScaler

#激活函数
def tanh(x):
return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))

#激活函数 tanh导数
def d_tanh(x):
return 1 + np.negative(np.square(tanh(x)))

#计算cost
def cost(a,y):
return np.negative(y * np.log(a)) + ((1 + np.negative(y)) * np.log(1 + np.negative(a)))

#计算dA
def da(a,y):
return np.negative(y / a) + ((1 + np.negative(y)) / (1 + np.negative(a)))

#自定义多层神经网络
def neuralNetwork(l,n,X,y,lr,iterations):
"""
loss function： -ylogy_hat + (1-y)log(1-y_hat)
params:
l : The number of layers
n : The number of nodes on each layer
X : x
y : y
lr : learning rate
iterations : Number of iterations
"""
A = [X]
W,b,Z = [0],[0],[0]
dZ,dA,dW,db = [0],[0],[0],[0]
m = X.shape[1]
loss = 1000
#初始化
for i in range(1,l):
W.append(np.random.rand(n[i],n[i-1]))
b.append(np.random.rand(n[i]).reshape(n[i],1))
A.append(0)
Z.append(0)
dZ.append(0)
dA.append(0)
dW.append(0)
db.append(0)

for index in range(iterations):
#前馈传播
for i in range(1,l):
Z[i] = np.dot(W[i],A[i-1]) + b[i].reshape(len(b[i]),1)
A[i] = tanh(Z[i])

#最后一层dA
"""
if((np.isnan(np.mean(cost(A[l-1], y)))) | (np.mean(cost(A[l-1], y)) == loss)):
print("迭代停止")
#break
else:"""
loss = np.mean(cost(A[l-1], y))
print(index,loss)
dA[l-1] =  da(A[l-1], y)

#反向传播
for i in range(1,l):
layer = l-i
dZ[layer] = dA[layer] * d_tanh(Z[layer]) #对应元素相乘
dW[layer] = 1/m * (np.dot(dZ[layer], A[layer-1].T))
db[layer] = 1/m * np.sum(dZ[layer], axis=1, keepdims=True)
dA[layer - 1] = np.dot(W[layer].T, dZ[layer])

#更新权值
W[layer] -= lr * dW[layer]
b[layer] -= lr * db[layer]

return A,W,b

#构造自编码器
def AutoEncoder(X,n,lr,it):
"""
loss function： -ylogy_hat + (1-y)log(1-y_hat)
params:
n : The number of nodes on each layer
X : x
lr : learning rate
iterations : Number of iterations
"""
row = X.shape[0]
col = X.shape[1]
X = X.reshape(row * col,1)
l = len(n)
scaler = MinMaxScaler().fit(X)
X_scaler = scaler.transform(X)
print(X_scaler.shape)
print("input ",X)
#print("归一化 ",X)
A,W,b = neuralNetwork(l,n,X_scaler,X_scaler,lr,it)
print("AutoEncoder output ",scaler.inverse_transform(A[l-1]).reshape(row,col))

#X = np.array([5,5,10,1,5,9,7,4,6,8])
#X = X.reshape(len(X),1)
#测试
from sklearn import datasets