Python 神经网络(感知器)-执行二元分类时可视化决策边界(作为超平面)

Python 神经网络(感知器)-执行二元分类时可视化决策边界(作为超平面),python,matplotlib,keras,neural-network,classification,Python,Matplotlib,Keras,Neural Network,Classification,我想可视化一个只有一个神经元(3个输入,二进制输出)的简单神经网络的决策边界。我从Keras NN模型中提取权重,然后尝试使用matplotlib绘制曲面。不幸的是,超平面没有出现在散点图上的点之间,而是显示在所有数据点下方(请参见输出图像) 我用这个方程计算超平面的z轴 z=(d-ax-by)/c对于定义为ax+by+cz=d的超平面 有人能帮助我正确地构造和显示基于NN权重的超平面吗 这里的目标是使用公共数据集()根据3个预测变量将个体分为两组(糖尿病组或非糖尿病组) 最好的猜测不需要阅读

我想可视化一个只有一个神经元(3个输入,二进制输出)的简单神经网络的决策边界。我从Keras NN模型中提取权重,然后尝试使用matplotlib绘制曲面。不幸的是,超平面没有出现在散点图上的点之间,而是显示在所有数据点下方(请参见输出图像)

我用这个方程计算超平面的z轴
z=(d-ax-by)/c
对于定义为
ax+by+cz=d的超平面

有人能帮助我正确地构造和显示基于NN权重的超平面吗

这里的目标是使用公共数据集()根据3个预测变量将个体分为两组(糖尿病组或非糖尿病组)


最好的猜测不需要阅读所有的代码细节。看起来你应用了乙状结肠激活。如果您在没有激活(activation='linear')的情况下进行训练,您应该可以获得所需的可视化效果。您可能需要更长时间的训练才能实现收敛(假设它可以在没有激活的情况下收敛)。如果你想保留乙状结肠,那么你需要通过这个激活映射你的线性神经元(因此它看起来不再像一个平面)

编辑:

我对NNs的理解。从3到1的致密层和sigmoid激活是优化方程中变量A、b、c、d的尝试:

f(x,y,z)=1/(1+e^(-D(x,y,z));D(x,y,z)=ax+by+cz+D

为了使二进制交叉熵(您选择的)最小化,我将使用B作为日志的总和。我们的损失方程如下所示:

L=∑ B(y,y)

其中,y是我们想要预测的值,在本例中为0或1,y是上述等式输出的值,总和加在所有数据(或NN中的批次)上。因此,可以这样写

L=∑ B(y,f(x,y,z))

求给定变量a、b、c、d的最小值L可能可以通过求偏导数和求解给定的方程组直接计算(这就是为什么NN永远不应该与一小部分变量(如4)一起使用,因为它们可以显式求解,因此训练没有意义).无论是直接求解还是使用stocastic梯度下降,都要缓慢地将a、b、c、d移到最小值;在任何情况下,我们最终得到优化的a、b、c、d

a、 b,c,d已经被调整到特定的值,当插入到sigmoid方程中时,会产生预测的类别,当在损失方程中进行测试时,会给我们带来最小的损失

但我坚持纠正。在这种情况下,因为我们有一个特别的sigmoid,然后建立和求解边界方程,似乎总是产生一个平面(我不知道)。我认为这不适用于任何其他激活或任何具有多个层的NN

1/2=1/(1+e^(-D(x,y,z))) ... D(x,y,z)=0 ax+by+cz+d=0

所以,我下载了你的数据并运行了你的代码。我一点也不收敛;我尝试了各种批量大小、损失函数和激活函数。什么都没有。从图片上看,几乎所有随机权重都倾向于远离集群,而不是试图找到集群的中心


您可能需要首先转换数据(在所有轴上进行规格化可能会起到作用),或手动将权重设置为中间的某个值,以便训练收敛。长话短说,你的a、b、c、d不是最优的。你也可以显式求解上面的偏导数,找到最优的a、b、c、d,而不是试图让单个神经元收敛。还有计算最优pla的显式方程分离二进制数据的ne(线性回归的一种扩展)。

最好的猜测不必阅读所有的详细代码。它看起来像是应用了一个sigmoid激活。如果在没有激活的情况下进行训练(activation='linear'),你应该得到你想要的可视化效果。你可能需要训练更长的时间才能获得收敛(假设它可以在没有激活的情况下收敛)。如果你想保留乙状结肠,那么你需要通过激活映射你的线性神经元(因此它看起来不再像一个平面)

编辑:

我对NNs的理解。从3到1的致密层和sigmoid激活是试图优化方程中的变量A、b、c、d:

f(x,y,z)=1/(1+e^(-D(x,y,z));D(x,y,z)=ax+by+cz+D

为了使二进制交叉熵(您选择的)最小化,我将使用B作为日志的总和。我们的损失方程如下所示:

L=∑ B(y,y)

其中,y是我们想要预测的值,在本例中为0或1,y是上述等式输出的值,总和加在所有数据(或NN中的批次)上。因此,可以这样写

L=∑ B(y,f(x,y,z))

求给定变量a、b、c、d的最小值L可能可以通过求偏导数和求解给定的方程组直接计算(这就是为什么NN永远不应该与一小部分变量(如4)一起使用,因为它们可以显式求解,因此训练没有意义).无论是直接求解还是使用stocastic梯度下降,都要缓慢地将a、b、c、d移到最小值;在任何情况下,我们最终得到优化的a、b、c、d

a、 b,c,d已经被调整到特定的值,当插入到sigmoid方程中时,会产生预测的类别,当在损失方程中进行测试时,会给我们带来最小的损失

但我坚持纠正。在这种情况下,因为我们有一个特别的sigmoid,然后建立和求解边界方程,似乎总是产生一个平面(我不知道)。我认为这不适用于任何其他激活或任何具有多个层的NN。
%matplotlib notebook

import pandas as pd
import numpy as np
from keras import models
from keras import layers
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

EPOCHS = 2

#Data source: https://www.kaggle.com/uciml/pima-indians-diabetes-database
ds = pd.read_csv('diabetes.csv', sep=',', header=0)

#subset and split
X = ds[['BMI', 'DiabetesPedigreeFunction', 'Glucose']]
Y = ds[['Outcome']]

#construct perceptron with 3 inputs and a single output
model = models.Sequential()
layer1 = layers.Dense(1, activation='sigmoid', input_shape=(3,))
model.add(layer1)

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

#train perceptron
history = model.fit(x=X, y=Y, epochs=EPOCHS)

#display accuracy and loss
epochs = range(len(history.epoch))

plt.figure()
plt.plot(epochs, history.history['accuracy'])
plt.xlabel('Epochs')
plt.ylabel('Accuracy')

plt.figure()
plt.plot(epochs, history.history['loss'])
plt.xlabel('Epochs')
plt.ylabel('Loss')

plt.show()

#extract weights and bias from model
weights = model.layers[0].get_weights()[0]
biases = model.layers[0].get_weights()[1]

w1 = weights[0][0] #a
w2 = weights[1][0] #b
w3 = weights[2][0] #c
b = biases[0]      #d

#construct hyperplane: ax + by + cz = d
a,b,c,d = w1,w2,w3,b

x_min = ds.BMI.min()
x_max = ds.BMI.max()

x = np.linspace(x_min, x_max, 100)

y_min = ds.DiabetesPedigreeFunction.min()
y_max = ds.DiabetesPedigreeFunction.max()

y = np.linspace(y_min, y_max, 100)

Xs,Ys = np.meshgrid(x,y)
Zs = (d - a*Xs - b*Ys) / c

#visualize 3d scatterplot with hyperplane
fig = plt.figure(num=None, figsize=(9, 9), dpi=100, facecolor='w', edgecolor='k')
ax = fig.gca(projection='3d')

ax.plot_surface(Xs, Ys, Zs, alpha=0.45)

ax.scatter(ds.BMI, ds.DiabetesPedigreeFunction, ds.Glucose, c=ds.Outcome)

ax.set_xlabel('BMI')
ax.set_ylabel('DiabetesPedigreeFunction')
ax.set_zlabel('Glucose')