自定义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])

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
神经网络可以用来实现二进制转十进制的功能。下面是一个简单的例子,展示了如何使用神经网络进行二进制到十进制的转换。 首先,我们需要准备训练数据。训练数据由一系列的二进制数和对应的十进制数组成。例如,对于一个4位的二进制数,我们可以准备以下训练数据: | 二进制数 | 十进制数 | |----------|----------| | 0000 | 0 | | 0001 | 1 | | 0010 | 2 | | 0011 | 3 | | 0100 | 4 | | 0101 | 5 | | 0110 | 6 | | 0111 | 7 | | 1000 | 8 | | 1001 | 9 | | ... | ... | 接下来,我们可以使用神经网络来拟合这些训练数据。一个简单的方法是使用一个多层感知机(MLP)神经网络。输入层有4个神经元,输出层有10个神经元(对应十进制的0到9)。中间可以有若干个隐藏层,具体的结构可以根据实际情况来确定。 在训练过程中,我们将二进制数作为输入,将十进制数作为目标输出。通过反向传播算法和梯度下降等优化方法,不断调整神经网络的权重和偏置,使得网络能够准确地将二进制数转换为对应的十进制数。 训练完成后,我们可以使用这个训练好的神经网络来进行二进制到十进制的转换。将一个二进制数输入神经网络,网络会输出对应的十进制数。 需要注意的是,这只是一个简单的示例,实际应用中可能需要更复杂的网络结构和更多的训练数据来提高转换的准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值