为了实现
Mykhaylo所建议的内容,我稍微修改了
Milo的代码,以便提供权重作为参数来影响每行的宽度。这个参数是可选的,因为为最后一层提供权重没有意义。
所有这些都是为了能够可视化我的解决方案
这个神经网络练习。我给出了二进制权重(0或1),这样权重为零的线就不会被绘制出来(以使图像更清晰)。
from matplotlib import pyplot
from math import cos, sin, atan
import numpy as np
class Neuron():
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self):
circle = pyplot.Circle((self.x, self.y), radius=neuron_radius, fill=False)
pyplot.gca().add_patch(circle)
class Layer():
def __init__(self, network, number_of_neurons, weights):
self.previous_layer = self.__get_previous_layer(network)
self.y = self.__calculate_layer_y_position()
self.neurons = self.__intialise_neurons(number_of_neurons)
self.weights = weights
def __intialise_neurons(self, number_of_neurons):
neurons = []
x = self.__calculate_left_margin_so_layer_is_centered(number_of_neurons)
for iteration in range(number_of_neurons):
neuron = Neuron(x, self.y)
neurons.append(neuron)
x += horizontal_distance_between_neurons
return neurons
def __calculate_left_margin_so_layer_is_centered(self, number_of_neurons):
return horizontal_distance_between_neurons * (number_of_neurons_in_widest_layer - number_of_neurons) / 2
def __calculate_layer_y_position(self):
if self.previous_layer:
return self.previous_layer.y + vertical_distance_between_layers
else:
return 0
def __get_previous_layer(self, network):
if len(network.layers) > 0:
return network.layers[-1]
else:
return None
def __line_between_two_neurons(self, neuron1, neuron2, linewidth):
angle = atan((neuron2.x - neuron1.x) / float(neuron2.y - neuron1.y))
x_adjustment = neuron_radius * sin(angle)
y_adjustment = neuron_radius * cos(angle)
line_x_data = (neuron1.x - x_adjustment, neuron2.x + x_adjustment)
line_y_data = (neuron1.y - y_adjustment, neuron2.y + y_adjustment)
line = pyplot.Line2D(line_x_data, line_y_data, linewidth=linewidth)
pyplot.gca().add_line(line)
def draw(self):
for this_layer_neuron_index in range(len(self.neurons)):
neuron = self.neurons[this_layer_neuron_index]
neuron.draw()
if self.previous_layer:
for previous_layer_neuron_index in range(len(self.previous_layer.neurons)):
previous_layer_neuron = self.previous_layer.neurons[previous_layer_neuron_index]
weight = self.previous_layer.weights[this_layer_neuron_index, previous_layer_neuron_index]
self.__line_between_two_neurons(neuron, previous_layer_neuron, weight)
class NeuralNetwork():
def __init__(self):
self.layers = []
def add_layer(self, number_of_neurons, weights=None):
layer = Layer(self, number_of_neurons, weights)
self.layers.append(layer)
def draw(self):
for layer in self.layers:
layer.draw()
pyplot.axis('scaled')
pyplot.show()
if __name__ == "__main__":
vertical_distance_between_layers = 6
horizontal_distance_between_neurons = 2
neuron_radius = 0.5
number_of_neurons_in_widest_layer = 4
network = NeuralNetwork()
weights1 = np.array([\
[0,0,0,0,0,0,0,0,1,1],\
[0,0,0,0,1,1,1,1,0,0],\
[0,0,1,1,0,0,1,1,0,0],\
[0,1,0,1,0,1,0,1,0,1]])
network.add_layer(10, weights1)
network.add_layer(4)
network.draw()