神经网络(感知器)–在进行二元分类时,将决策边界(以超平面的形式)可视化。

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

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

谁能帮助我正确构建和显示基于NN权重的超平面?

Output:

这里的目标是根据3个预测变量,使用一个公共数据集,将个人分为两组(糖尿病或无糖尿病)(https:/www.kaggle.comucimlpima-indians-diabetes-database).

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

解决方案:

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

EDIT:

我对NN的理解。从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))

找出L个给定变量a,b,c,d的最小值,可能可以直接通过取部分导数和求解给定方程组来计算(这就是为什么NN永远不应该用小变量集(比如4),因为它们可以被显式求解,所以没有训练的意义)。不管是直接求解,还是使用stocastic gradient decent慢慢地将a,b,c,d向最小值移动;无论如何,我们最终都会得到优化后的a,b,c,d。

a,b,c,d必须被调整为专门产生的值,当插入sigmoid方程时,产生预测的类别,当在损失方程中测试时,会给我们一个最小的损失。

不过我的观点是正确的。在这种情况下,因为我们有专门的sigmoid,然后设置和解决边界方程,确实似乎总是产生一个平面(不知道)。我不认为这将与任何其他激活或与任何NN有一个以上的层。

12 = 1(1+e^(-D(x,y,z)))…D(x,y,z)=0ax+by+cz+d = 0

所以,我下载了你的数据并运行了你的代码。我完全没有得到收敛;我尝试了各种批次_大小,损失函数和激活函数。什么都没有。根据图片,似乎是可信的,几乎每一个随机化的权重都会倾向于远离集群,而不是试图找到它的中心。

你可能需要先转换你的数据(在所有轴上进行归一化可能会有效果),或者手动将你的权重设置为中心的东西,这样训练就会收敛。长话短说,你的a,b,c,d都不是最优的。你也可以明确地解决上面的部分导数,找到最优的a,b,c,d,而不是试图让单个神经元收敛。还有明确的方程用于计算分离二进制数据的最优平面(线性回归的扩展)。

给TA打赏
共{{data.count}}人
人已打赏
未分类

道具在vue js中被突变了。

2022-9-8 15:46:25

未分类

在Docker容器中使用Angular的AspNetCore应用程序没有响应。

2022-9-8 15:57:20

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索