神经网络/自编码器的实现(向量化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
iris = datasets.load_iris()
data = iris["data"]

X = data
row = X.shape[0]
col = X.shape[1]

AutoEncoder(X,[row * col,2,row * col],0.05,100)

此版本目前存在一个Bug 在自编码器中,当对输入标准化之后,等于或接近零的数值在还原之后变成了负数。 解释半天找不到原因,有没有大佬知道是什么原因的,欢迎指出问题所在,谢谢。

猜你喜欢

转载自blog.csdn.net/machinerandy/article/details/79546994