【问题标题】:Neural network (perceptron) - visualizing decision boundary (as a hyperplane) when performing binary classification神经网络(感知器) - 在执行二元分类时可视化决策边界(作为超平面)
【发布时间】:2020-08-07 14:21:29
【问题描述】:

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

我正在使用等式计算超平面的 z 轴 z = (d - ax - by) / c 用于定义为 ax + by + cz = d 的超平面

有人可以帮助我根据 NN 权重正确构建和显示超平面吗?

这里的目标是使用公共数据集 (https://www.kaggle.com/uciml/pima-indians-diabetes-database) 根据 3 个预测变量将个体分为两组(糖尿病或非糖尿病)。

%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')

【问题讨论】:

    标签: python matplotlib keras neural-network classification


    【解决方案1】:

    你的网络是一个逻辑回归模型,所以表面的方程肯定是 z = (-b-w1x -w2y) / w3 。你的模型需要更多的训练。尝试增加 epoch 的数量(尝试大约 500):

    由于您的数据不是线性可分的,因此您需要在网络中添加隐藏层,以便了解输入的转换,使其成为线性可分。不过,绘制决策边界并不那么简单......

    【讨论】:

    • 您是否在与我介绍的相同模型上生成了这个可视化,但只有更多的时期?我知道这些类不会是线性可分的,但我只是想演示 NN 在最简单的情况下是如何工作的。另外,为什么你有一个负偏差项?我认为应该是 z = (b - w1x - w2y) / w3
    • 是的,这与您发布的代码完全相同,但方程式中的偏差项发生了变化,并且时期也发生了变化。在逻辑回归中,分离超平面恰好是预测概率为 1/2 的地方。当 σ(w1x + w2y + w3z + b) = 1/2 时会发生这种情况,这只发生在 w1x + w2y + w3z + b = 0 时。将所有内容移到等式的一侧,使其成为 z 的函数,我们得到: z = (-b - w1x - w2y) / w3。希望有帮助!
    • 非常感谢您对此的想法。为什么你制作的可视化是颠倒的?
    • 在 matplotlib 中,您可以在保存之前用光标移动 3d 图。我移动它是为了最好地显示通过点的表面。当您移动它时,轴可能也会移动,因此您正在绘制的内容仍然可见。在这里,如果糖尿病和 BMI 轴位于底部,我们将通过该平面查看一些点
    【解决方案2】:

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

    编辑:

    我对神经网络的理解。从 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

    为了使 binary_crossentropy(你选择的)最小化,我将使用 B 作为日志的总和。我们的损失方程看起来像:

    L = ∑ B(y,Y)

    其中 y 是我们想要预测的值,在这种情况下为 0 或 1,Y 是上面等式输出的值,总和会添加到所有数据(或 NN 中的批次)。因此,这可以写成

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

    找到 L 给定变量 a,b,c,d 的最小值可能可以直接通过取偏导数并求解给定方程组来计算(这就是为什么 NN 永远不应该与一小组变量一起使用(例如4),因为可以显式求解,所以训练没有意义)。无论是直接求解还是使用随机梯度体面将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,而不是试图让单个神经元收敛。还有用于计算分离二进制数据的最佳平面的显式方程(线性回归的扩展)。

    【讨论】:

    • 我的结果是二元的,因此是 sigmoid 激活。此外,输入的加权和确实会产生一个平面。但是,在构建飞机时,我要么错过了一些事情,要么做错了一些事情。
    • 仅仅因为您希望输出是二进制的,并不意味着您没有通过指数函数映射线性密集层。无论您希望您的结果数据是什么样子,该 sigmoid 都必须发挥作用。
    • 您可以尝试换一种方式。如果您通过对数映射所有数据点会发生什么情况,它们是否与您的飞机对齐?
    • 决策边界由输入的加权和决定,而不是输出层。执行分类的是学习到的权重。
    • 我没有关注你,我可能对神经网络有些不了解。让我编辑我的答案,如果你能解释我的误解,那将对我有很大帮助。
    【解决方案3】:

    您网络的决策边界不是ax + by + cz = d,而是ax + by + cz + d = 0

    【讨论】:

    • 感谢@Julien。我尝试将我的方程式更改为Zs = ((d + a*Xs + b*Ys) / c)*(-1),但这并没有解决我的问题。平面仍然没有分离任何点。还有什么建议吗?
    猜你喜欢
    • 2015-12-31
    • 2015-09-06
    • 2019-06-21
    • 2015-01-27
    • 2017-08-31
    • 2013-10-04
    • 2015-11-12
    • 2018-11-08
    相关资源
    最近更新 更多