自定义MLP实现八位二进制数字奇偶校验

(本人最初发布于HackMD:HackMD链接,链接内容为繁体字)

1.问题描述

自定义一个MLP来学习8位奇偶校验(8BPC)问题8BPC问题是从8位(1字节)二进制输入生成单个奇偶校验位 如果二进制输入中的数字1为奇数,则生成的奇偶校验位必须为1;否则,生成的奇偶校验位必须为零。

2.产生训练数据(data和labels)

八个二进制位,一共有256种不同的组合,也就是相当于把0-256转换为二进制的形式表示,然后根据奇偶,将得到1或0的label。

#首先生成训练和测试所用的data和labels
#八个二进制位,一共有256种不同的组合,也就是相当于把0-256转换为二进制的形式表示,然后根据奇偶,将得到1或0的label
import numpy as np
def getParityBit(bitString:str) -> int:
    if type(bitString) is not str:
        raise TypeError('Expected str; got %s' % type(bitString))
    parityBit = False
    for c in bitString:
        if c == '1':
            parityBit = not parityBit
            
    rel = 1 if parityBit else 0
    return rel
def createDataAndLabels():
    data = []
    labels = []
    for i in range(256):
        intToBinary = '{0:08b}'.format(i)
        data.append(list(map(int, intToBinary)))
        labels.append([getParityBit(intToBinary)])
    return (np.array(data), np.array(labels))

3.定义所用到的激活函数

#定义需要用到的激活函数,tanh,ReLU,Sigmoid
import numpy as np
class tanh:
    def __init__(self):
        pass

    def forward(self, x):
        out = np.tanh(x)
        self.o = out
        return out

    def backward(self, dout):
        dx = dout*(1.0 - self.o**2)
        return dx
class ReLU:
    def __init__(self):
        pass

    def forward(self, x):
        self.mask = (x<=0)
        out = x
        out[out<=0] = 0
        return out

    def backward(self, dout):
        dx = dout
        dx[self.mask] = 0
        return dx

class Sigmoid:
    def __init__(self):
        pass

    def forward(self, x):
        out = 1.0/(1+np.exp(-x))
        self.o = out
        return out

    def backward(self, dout):
        dx = dout*self.o*(1-self.o)
        return dx

#定义loss function
class Loss:
    def __init__(self):
        pass
    def forward(self, y, ybar):
        self.y = y
        self.ybar = ybar
        return np.sum((y-ybar)**2)
    def backward(self, dout):
        dy = -(2*(self.y -self.ybar))
        return dy
    
#该神经网络使用线性神经网络
class Linear:
    def __init__(self, m, n):
        self.W = np.random.randn(m, n)/8.0
        self.b = np.random.rand(1, n)/8.0
        self.dW, self.db = None, None
    
    def forward(self, x):
        self.x = x
        out = np.dot(x, self.W)+self.b
        return out
    
    def backward(self, dout):
        dx = np.dot(dout, self.W.T)
        self.dW = np.dot(self.x.T, dout)
        self.db = np.sum(dout, axis=0)
        return dx

4.创建MLP_Model类

#定义MLP_Model类,可以用来创建模型
class MLP_Model:
    def __init__(self, inDegree:int, layerType:list, outDegree):
        self.degree = list(map(int, str(inDegree))) + outDegree
        layerType = [x.lower() for x in layerType]
        self.supportFuncTable = {
            'relu' : ReLU,
            'sigmoid' : Sigmoid,
            'tanh' : tanh
            }
        
        self.layers = []
        self.actFunctions = []
        self.last_dW ,self.last_db = [], []
        for i in range(len(self.degree)-1):
            self.layers.append(Linear(self.degree[i], self.degree[i+1]))
            self.actFunctions.append(self.supportFuncTable[layerType[i]]())
            self.last_dW.append(0)
            self.last_db.append(0)
            self.loss = Loss()

    def forward(self, x):
        for i in range(len(self.layers) - 1):
            x = self.layers[i].forward(x)
            x = self.actFunctions[i].forward(x)
        x = self.layers[-1].forward(x)
        self.ybar = self.actFunctions[-1].forward(x)
        return self.ybar 

    def backward(self, y):
        self.L = self.loss.forward(y, self.ybar)
        g = self.loss.backward(1)
        for i in range(len(self.layers)-1, -1, -1):
            g = self.actFunctions[i].backward(g)
            g = self.layers[i].backward(g)
    
    def update(self, eta, alpha):
        for i in range(len(self.layers)):
            self.layers[i].W += -eta*self.layers[i].dW + alpha*self.last_dW[i]
            self.layers[i].b += -eta*self.layers[i].db + alpha*self.last_db[i]
            self.last_dW[i] = eta*self.layers[i].dW
            self.last_db[i] = eta*self.layers[i].db
            
    #predict方法用来预测结果
    def predict(self, x):
        self.forward(x)
        return np.array([1]) if model.ybar > 0.5 else np.array([0])

5.创建并训练模型

使用刚才定义的createDataAndLabels函数,产生data和labels

Data, Labels = createDataAndLabels()

①使用两层神经网(ReLU+Sigmoid)

先创建一个具有一个Relu层和一个sigmoid层的模型

#定义模型model,每一笔data的维度为8,第一层的激活函数为relu,然后是sigmoid得到一个数值,也就是输出
model = MLP_Model(8, 
            ['relu', 'sigmoid'],
            [100,  1])

#设置eta和alpha为0.001和0.0001
eta, alpha = 0.001, 0.0001

#将epochs设置为20000,每隔100个epochs显示一次
max_epochs, check_epochs = 20000, 100


printPointOfEporch = []
printPointOfLoss = []

for e in range(max_epochs):
    model.forward(Data)
    model.backward(Labels)
    model.update(eta, alpha)
    #每隔100个epochs显示一次loss
    if (e+1) % check_epochs == 0:
        print('epoch:{0:2d}------loss:{1:2.4f}'.format(e+1, model.L))
        printPointOfEporch.append(e), printPointOfLoss.append(model.L)

打印训练过程

#打印训练过程
import matplotlib.pyplot as plt
import numpy as np

plt.title("only one relu layer")
#根据刚才设置的20000÷100=200个loss结果,来打印训练过程
plt.plot(printPointOfEporch, printPointOfLoss)
plt.show()

在这里插入图片描述

②使用三层神经网(ReLU+ReLU+Sigmoid)

创建一个具有两个ReLU层和一个Sigmoid层的模型

#定义一个三层神经网的模型
model = MLP_Model(8, 
            ['relu', 'relu', 'sigmoid'],
            [100,40,1])

#设置eta和alpha为0.001和0.0001
eta, alpha = 0.001, 0.0001

#将epochs设置为20000,每隔100个epochs显示一次
max_epochs, check_epochs = 20000, 100


printPointOfEporch = []
printPointOfLoss = []

for e in range(max_epochs):
    model.forward(Data)
    model.backward(Labels)
    model.update(eta, alpha)
    #每隔100个epochs显示一次loss
    if (e+1) % check_epochs == 0:
        print('epoch:{0:2d}------loss:{1:2.4f}'.format(e+1, model.L))
        printPointOfEporch.append(e), printPointOfLoss.append(model.L)

打印训练过程

#打印训练过程

import matplotlib.pyplot as plt
import numpy as np

plt.title("two relu layers")
#根据刚才设置的20000÷100=200个loss结果,来打印训练过程
plt.plot(printPointOfEporch, printPointOfLoss)
plt.show()

在这里插入图片描述

③使用四层神经网(ReLU+ReLU+ReLU+Sigmoid)

创建具有三个ReLU层和一个Sigmoid层的模型

#定义一个四层神经网的模型
model = MLP_Model(8, 
            ['relu', 'relu', 'relu', 'sigmoid'],
            [100,70,30,1])

#设置eta和alpha为0.001和0.0001
eta, alpha = 0.001, 0.0001

#将epochs设置为20000,每隔100个epochs显示一次
max_epochs, check_epochs = 20000, 100


printPointOfEporch = []
printPointOfLoss = []

for e in range(max_epochs):
    model.forward(Data)
    model.backward(Labels)
    model.update(eta, alpha)
    #每隔100个epochs显示一次loss
    if (e+1) % check_epochs == 0:
        print('epoch:{0:2d}------loss:{1:2.4f}'.format(e+1, model.L))
        printPointOfEporch.append(e), printPointOfLoss.append(model.L)

打印训练过程

#打印训练过程

import matplotlib.pyplot as plt
import numpy as np

plt.title("three relu layers")
#根据刚才设置的20000÷100=200个loss结果,来打印训练过程
plt.plot(printPointOfEporch, printPointOfLoss)
plt.show()

在这里插入图片描述

6.测试模型

#预测一下结果
model.predict([1,0,1,1,0,1,1,0])

在这里插入图片描述

model.predict([0,1,0,1,1,1,0,0])

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值