1、什么是异或?
异或是一种二元运算&。
一位二进制数的&运算规则为:
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
0 ^ 0 = 0
提问:11&22 等于多少?
先把11化为5位二进制数,得到
(
01011
)
2
(01011)_2
(01011)2,
再把22化为5位二进制数,得到
(
10110
)
2
(10110)_2
(10110)2,
分别对5个二进制位进行^运算。
由于只有右边第二位有相同的1,其他各位都各不相同,
所以结果为,
(
11101
)
2
(11101)_2
(11101)2,化为十进制得到29。
print('bin(11) =',bin(11))
print('bin(11) =',bin(22))
print('11^22 =', 11^22)
回答:结果为
bin(11) = 0b1011
bin(11) = 0b10110
11^22 = 29
2、异或是线性不可分的
把上面运算规则中等式左边的数字作为点的坐标,等式右边的数字作为点的类型,就有了两种类型的四个点,把它画到平面直角坐标系中如下图,
红色和蓝色代表点的类型。显然,无法找出一条直线将两类点分开,这就是说,这些点不是线性可分的。
3、用逻辑回归建模
用这四个点训练逻辑回归模型,看看能不能正确分类。
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
x = np.array([[0,1], [0,0], [1,0], [1,1]])
y = np.array([1, 0, 1, 0])
mm = LogisticRegression()
mm.fit(x,y)
y_hat = mm.predict(x)
acc = accuracy_score(y_hat, y)
print(acc)
运行结果如下,准确率只有0.5。
0.5
4、用简单神经网络处理异或
如何用pytorch建立神经网络?
对于训练数据(x, y),先确定神经网络的结构,然后迭代执行下列操作,
(1)由正向传播forward(x)计算预测结果y_hat;
(2)用损失函数loss_function(y_hat, y)计算偏差;
(3)由反向传播backward()计算模型参数的导数
(4)用优化函数step()来更新模型参数。
每一步都力求减小偏差。最后评估模型的性能。
下面准备代码。
(1)先确定网络结构如下,
(2)生成500个数据点,line 8;
(3)计算这些点的类型,使之成为异或(交叉)形状,line 9;
(4)设计类mm_cls,定义神经网络。这个类要继承自Module,以便于提取模型参数调用mm.parameters()即可。__init__定义模型结构,其中l2可放置Sigmoid函数,这里用一个平方函数也能起到类似作用。forward用于计算预测结果,line 11-26;
(5)定义损失函数。分类问题可用交叉熵,这里使用了更容易理解的均方差,line 28;
(6)定义优化函数,调用Adam,它是最为常用的优化算法之一,line 29;
(7)开始训练模型,训练过程主要由5个函数,forward、loss_fun、backward、step、zero_grad组成,line 31-41;
(8)取得真实结果和预测结果,把结果变为50个0或者1,line 43-44;
(9)计算准确率,line 46-47;
(10)绘制真实结果和预测结果。
代码如下,
import torch
import torch.nn as nn
from sklearn.metrics import accuracy_score
torch.manual_seed(1234)
n = 500
x = torch.rand(n, 2)*2 - 1
y = torch.Tensor([[1,0] if k[0]*k[1]>0 else [0, 1] for k in x])
class mm_cls(torch.nn.Module):
def __init__(self):
super(mm_cls, self).__init__()
self.l1 = torch.nn.Linear(2, 5)
self.l2 = lambda x: x**2
self.l3 = torch.nn.Linear(5, 2)
self.l4 = nn.Softmax(dim=1)
def forward(self, x):
x1 = self.l1(x)
x2 = self.l2(x1)
x3 = self.l3(x2)
x4 = self.l4(x3)
return x4
mm = mm_cls()
loss_fun = torch.nn.MSELoss()
optimizer = torch.optim.Adam(mm.parameters(),lr=0.001)
epochs = 2000
for i in range(epochs):
y_hat = mm.forward(x)
loss = loss_fun(y_hat, y)
loss.backward()
optimizer.step()
if i % 100 == 0:
print('step = %4d'%i, 'loss = %.4e'%loss.item())
optimizer.zero_grad
y_hat = y_hat[:,0] < y_hat[:,1]
y = y[:,0] < y[:,1]
acc = accuracy_score(y_hat, y)
print('acc = %f' % acc)
import matplotlib.pyplot as plt
plt.subplot(121)
plt.plot(x[y==1, 0], x[y==1, 1], 'om')
plt.plot(x[y==0, 0], x[y==0, 1], 'ob')
plt.title('original')
plt.subplot(122)
plt.lot(x[y_hat==1, 0], x[y_hat==1, 1], 'om')
plt.plot(x[y_hat==0, 0], x[y_hat==0, 1], 'ob')
plt.title('predicted')
运行结果
step = 0 loss = 3.0564e-01
step = 100 loss = 2.5732e-01
step = 200 loss = 2.0864e-01
step = 300 loss = 1.4089e-01
step = 400 loss = 9.5052e-02
step = 500 loss = 6.8628e-02
step = 600 loss = 5.5190e-02
step = 700 loss = 4.3967e-02
step = 800 loss = 3.8397e-02
step = 900 loss = 3.3949e-02
step = 1000 loss = 2.3727e-02
step = 1100 loss = 3.0124e-02
step = 1200 loss = 1.7051e-02
step = 1300 loss = 3.3124e-02
step = 1400 loss = 1.5228e-02
step = 1500 loss = 2.5390e-02
step = 1600 loss = 2.5443e-02
step = 1700 loss = 1.6697e-02
step = 1800 loss = 2.9582e-02
step = 1900 loss = 2.5630e-02
acc = 0.990000
总结,通过一个经典的问题,介绍了在pytorch中建立简单模型的基本方法。
【上一篇:梯度下降】
【下一篇:repeat】