全文共4630字,预计学习时长12分钟

图源:unsplash
谈起神经网络,首先要谈到的是训练数据集。我们将生成三个数据集片段来演示如何处理两个以上的分类。每个片段包含两个坐标数组,我们通过指定这些点的区间来将其分组。因此,每个片段将分别以点0,-3,3,3,-3,3为中心,且每一片段对应一个输出。
下面是原始数据的生成情况:

接下来把三个片段结合成一个数据集并进行标记,这样神经网络就可以对其进行识别。

下面是数据的情况:

下一步是生成神经网络的所有参数,比如隐藏层和输出层的权重和偏差。神经网络的结构非常相似,只是输出层不同。

下面是生成参数的代码:

之前只使用了S型激活函数,其效果非常好。但因为现在输出层有三个分类,所以最好使用其他激活函数。
现在可以使用softmax函数。在有两个以上分类的情况下,通常在输出层使用这个函数。因为如果输出有三个元素,可以将每个元素的输出视为输入层的一个元素。softmax函数的数学表达为:

简单来说,softmax函数就是将每个输入元素的指数除以每个输入元素的指数之和。在python中,softmax函数的表达为:

现在可以继续训练这个模型了。
训练流程与二值分类非常相似,有前馈传播和反向传播阶段。但因为我们在输出层使用了不同的激活函数,所以会有一些区别。在前馈传播过程中,仍在隐藏层使用S型激活函数。softmax函数将在输出层使用。

而在反向传播阶段,重新计算了输出层的权重和偏差,作为softmax函数的结果。其余操作基本相同。

计算softmax产生的误差代价时,使用交叉熵函数而非均方。交叉熵函数是所有标记概率的总和,且预测概率的对数为负。下面是交叉熵函数的数学表达:

到这里生成数据和训练模型的准备工作就完成了,现在进行测试。
训练完成后,可以使用得到的权重和偏差来测试随机数据点。在测试过程中,复制前馈传播过程而非反向传播过程,因为权重和偏差已经训练过了,无需更新。
softmax函数输出为数组形式后,找到一个最大值的索引,这将是这个数据点的标签。向训练数据集和标签集添加一个新的数据点及其标签后,可以用肉眼测试它是否接近事实。
现在尝试50000次交互,以确保成本函数得到了很好的优化。第一个坐标是[0.0, 0.5],下面是模型在图上标注的方式:

关于位置的解码,只需记住,在softmax函数的输出中,数组有3个元素。元素索引0表示蓝色标签,元素索引1表示粉色,元素索引2表示黄色。我们可以看到,模型非常肯定这个点是蓝色的,而通过图示可以发现,它的预测是正确的。
下一个坐标是[-2.0,1.0],模型非常确信它是黄色的。

最后一个测试坐标是[2.0,-0.5]。模型只能肯定它不是黄色的。预测结果更倾向于蓝色,但不能十分肯定。但对于边缘坐标来说,这是一个很好的结果了。

全部代码:
import numpy as np
import matplotlib.pyplot as plt
classNN():
def__init__(self):
np.random.seed(42)
self.learning_rate =10e-4
defdata_gen(self, data_size):
segment_1 = np.random.randn(data_size, 2) + np.array([0, -3])
segment_2 = np.random.randn(data_size, 2) + np.array([3, 3])
segment_3 = np.random.randn(data_size, 2) + np.array([-3, 3])
self.training_set = np.vstack([segment_1, segment_2, segment_3])
self.labels = np.array([0]*data_size + [1]*data_size + [2]*data_size)
self.combined_labels = np.zeros((len(self.training_set),3))
for i inrange(len(self.training_set)):
self.combined_labels[i][self.labels[i]]=1
print('Data generated!')
defparameters_gen(self):
instances = self.training_set.shape[0]
attributes = self.training_set.shape[1]
hidden_nodes =4
output_labels =len(self.combined_labels[0])
self.weights_hidden = np.random.rand(attributes, hidden_nodes)
self.bias_h = np.random.randn(hidden_nodes)
self.weights_output = np.random.rand(hidden_nodes,output_labels)
self.bias_o = np.random.randn(output_labels)
print('Parameters generated!')
defvisualization(self, sample, label):
data = np.vstack([self.training_set, sample])
self.combined_labels = np.append(self.labels, label)
plt.figure(figsize=(10,7))
plt.scatter(data[:,0], data[:,1], c=self.combined_labels, cmap='plasma', s=100, alpha=0.5)
plt.show()
defsigmoid(self, x):
return1/(1+np.exp(-x))
defsigmoid_der(self, x):
return self.sigmoid(x) *(1-self.sigmoid (x))
defsoftmax(self, x):
try:
x.shape[1]
index =1
exceptIndexError:
index =0
expx = np.exp(x)
return expx / expx.sum(axis=index, keepdims=True)
deftraining(self, iterations):
error_cost = []
for i inrange(iterations):
########## Feedforward
########## Step 1 - Hidden layer
X= np.dot(self.training_set, self.weights_hidden) + self.bias_h
prediction_h = self.sigmoid(X)
########## Step 2 - Output layer
y = np.dot(prediction_h, self.weights_output) + self.bias_o
prediction_o = self.softmax(y)
########## Back Propagation
########## Step 1 - Output layer
pred_h = prediction_h
error_cost_o = prediction_o -self.combined_labels
der_cost_o = np.dot(pred_h.T, error_cost_o)
dcost_bo = error_cost_o
########## Step 2 - Hidden layer
weight_o = self.weights_output
error_cost_h = np.dot(error_cost_o , weight_o.T)
derivative_h = self.sigmoid_der(X)
taining_data = self.training_set
der_cost_h = np.dot(taining_data.T, derivative_h * error_cost_h)
dcost_bh = error_cost_h * derivative_h
########## Update Weights and Biases
self.weights_hidden -= self.learning_rate * der_cost_h
self.bias_h -= self.learning_rate * dcost_bh.sum(axis=0)
self.weights_output -= self.learning_rate * der_cost_o
self.bias_o -= self.learning_rate * dcost_bo.sum(axis=0)
loss = np.sum(-self.combined_labels * np.log(prediction_o))
# print('Loss function value: ', loss)
error_cost.append(loss)
print('Loss functionvalue: ', error_cost[-1])
deftest(self, sample):
np.set_printoptions(suppress=True, formatter={'float_kind':'{:f}'.format})
X= np.dot(sample, self.weights_hidden)+ self.bias_h
hidden_layer = self.sigmoid(X)
y = np.dot(hidden_layer, self.weights_output) + self.bias_o
output_layer = self.softmax(y)
print(output_layer)
label = np.argmax(output_layer)
self.visualization(sample, label)
########################### Execution###############################
net =NN()
# Generating data
net.data_gen(500)
# Generating weights and biases
net.parameters_gen()
# Training model
net.training(50000)
# Testing model
net.test(np.array([2.0, -0.5]))
本文中我们学习了如何修改神经网络使其能够解决多分类问题。现在可以使用真实的数据集来解决真实的问题了!

留言点赞关注
我们一起分享AI学习与发展的干货
如转载,请后台留言,遵守转载规范