Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
81 lines (72 loc) · 4.05 KB

File metadata and controls

81 lines (72 loc) · 4.05 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# network.py
# From Classic Computer Science Problems in Python Chapter 7
# Copyright 2018 David Kopec
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from typing import List, Callable, TypeVar, Tuple
from functools import reduce
from layer import Layer
from util import sigmoid, derivative_sigmoid
T = TypeVar('T') # output type of interpretation of neural network
class Network:
def __init__(self, layer_structure: List[int], learning_rate: float, activation_function: Callable[[float], float] = sigmoid, derivative_activation_function: Callable[[float], float] = derivative_sigmoid) -> None:
if len(layer_structure) < 3:
raise ValueError("Error: Should be at least 3 layers (1 input, 1 hidden, 1 output)")
self.layers: List[Layer] = []
# input layer
input_layer: Layer = Layer(None, layer_structure[0], learning_rate, activation_function, derivative_activation_function)
self.layers.append(input_layer)
# hidden layers and output layer
for previous, num_neurons in enumerate(layer_structure[1::]):
next_layer = Layer(self.layers[previous], num_neurons, learning_rate, activation_function, derivative_activation_function)
self.layers.append(next_layer)
# Pushes input data to the first layer, then output from the first
# as input to the second, second to the third, etc.
def outputs(self, input: List[float]) -> List[float]:
return reduce(lambda inputs, layer: layer.outputs(inputs), self.layers, input)
# Figure out each neuron's changes based on the errors of the output
# versus the expected outcome
def backpropagate(self, expected: List[float]) -> None:
# calculate delta for output layer neurons
last_layer: int = len(self.layers) - 1
self.layers[last_layer].calculate_deltas_for_output_layer(expected)
# calculate delta for hidden layers in reverse order
for l in range(last_layer - 1, 0, -1):
self.layers[l].calculate_deltas_for_hidden_layer(self.layers[l + 1])
# backpropagate() doesn't actually change any weights
# this function uses the deltas calculated in backpropagate() to
# actually make changes to the weights
def update_weights(self) -> None:
for layer in self.layers[1:]: # skip input layer
for neuron in layer.neurons:
for w in range(len(neuron.weights)):
neuron.weights[w] = neuron.weights[w] + (neuron.learning_rate * (layer.previous_layer.output_cache[w]) * neuron.delta)
# train() uses the results of outputs() run over many inputs and compared
# against expecteds to feed backpropagate() and update_weights()
def train(self, inputs: List[List[float]], expecteds: List[List[float]]) -> None:
for location, xs in enumerate(inputs):
ys: List[float] = expecteds[location]
outs: List[float] = self.outputs(xs)
self.backpropagate(ys)
self.update_weights()
# for generalized results that require classification this function will return
# the correct number of trials and the percentage correct out of the total
def validate(self, inputs: List[List[float]], expecteds: List[T], interpret_output: Callable[[List[float]], T]) -> Tuple[int, int, float]:
correct: int = 0
for input, expected in zip(inputs, expecteds):
result: T = interpret_output(self.outputs(input))
if result == expected:
correct += 1
percentage: float = correct / len(inputs)
return correct, len(inputs), percentage
Morty Proxy This is a proxified and sanitized view of the page, visit original site.