Это гораздо больше, чем ответ на конкретный вопрос, но после чата в комментариях и изучения того, что вопрос был конкретно частью нейронной сети в F #, я публикую это, которое охватывает вопрос и реализует часть нейронной сети с прямой связью. . Он использует MathNet Numerics.
Этот код представляет собой перевод на F# части кода Python из раздела Neural Networks and Deep Learning.
питон
def backprop(self, x, y):
"""Return a tuple ``(nabla_b, nabla_w)`` representing the
gradient for the cost function C_x. ``nabla_b`` and
``nabla_w`` are layer-by-layer lists of numpy arrays, similar
to ``self.biases`` and ``self.weights``."""
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
# feedforward
activation = x
activations = [x] # list to store all the activations, layer by layer
zs = [] # list to store all the z vectors, layer by layer
for b, w in zip(self.biases, self.weights):
z = np.dot(w, activation)+b
zs.append(z)
activation = sigmoid(z)
activations.append(activation)
F#
module NeuralNetwork1 =
//# Third-party libraries
open MathNet.Numerics.Distributions // Normal.Sample
open MathNet.Numerics.LinearAlgebra // Matrix
type Network(sizes : int array) =
let mutable (_biases : Matrix<double> list) = []
let mutable (_weights : Matrix<double> list) = []
member __.Biases
with get() = _biases
and set value =
_biases <- value
member __.Weights
with get() = _weights
and set value =
_weights <- value
member __.Backprop (x : Matrix<double>) (y : Matrix<double>) =
// Note: There is a separate member for feedforward. This one is only used within Backprop
// Note: In the text layers are numbered from 1 to n with 1 being the input and n being the output
// In the code layers are numbered from 0 to n-1 with 0 being the input and n-1 being the output
// Layers
// 1 2 3 Text
// 0 1 2 Code
// 784 -> 30 -> 10
let feedforward () : (Matrix<double> list * Matrix<double> list) =
let (bw : (Matrix<double> * Matrix<double>) list) = List.zip __.Biases __.Weights
let rec feedfowardInner layer activation zs activations =
match layer with
| x when x < (__.NumLayers - 1) ->
let (bias, weight) = bw.[layer]
let z = weight * activation + bias
let activation = __.Sigmoid z
feedfowardInner (layer + 1) activation (z :: zs) (activation :: activations)
| _ ->
// Normally with recursive functions that build list for returning
// the final list(s) would be reversed before returning.
// However since the returned list will be accessed in reverse order
// for the backpropagation step, we leave them in the reverse order.
(zs, activations)
feedfowardInner 0 x [] [x]
В weight * activation
* есть перегруженный оператор, работающий с Matrix<double>
Связано с данными вашего примера и использованием MathNet Numerics Арифметика
let weights = [0.5;0.4;0.3]
let X = [[2;3;4];[7;3;2];[5;3;6]]
сначала значения для X необходимо преобразовать в число с плавающей запятой
let x1 = [[2.0;3.0;4.0];[7.0;3.0;2.0];[5.0;3;0;6;0]]
Теперь обратите внимание, что x1 — это матрица, а веса — вектор.
так что мы можем просто умножить
let wx1 = weights * x1
Поскольку способ, которым я проверил код, был немного сложнее, чем у большинства, я объясню его, чтобы у вас не было сомнений в его достоверности.
При работе с нейронными сетями и, в частности, с мини-пакетами начальные числа для весов и смещений являются случайными, и генерация мини-пакетов также выполняется случайным образом.
Я знаю, что исходный код Python был действительным, и я смог успешно запустить его и получить такие же результаты, как указано в книге, а это означает, что первоначальные успехи были в пределах пары процентов от книги, а графики успеха были такими же. . Я сделал это для нескольких прогонов и нескольких конфигураций нейронной сети, как описано в книге. Затем я запустил код F# и получил такие же графики.
Я также скопировал начальные наборы случайных чисел из кода Python в код F#, чтобы, хотя генерируемые данные были случайными, и код Python, и код F# использовали одни и те же начальные числа, которых тысячи. Затем я пошагово выполнил код Python и F#, чтобы убедиться, что каждая отдельная функция возвращает сопоставимое значение с плавающей запятой, например Я поставил точку останова на каждой строке и убедился, что проверил каждую. На самом деле это заняло несколько дней, потому что мне нужно было написать код экспорта и импорта и передать данные из Python в F#.
См.: Как определить тип вложенных структур данных в Python. ?
Я также попробовал вариант, в котором я заменил список F # на связанный список, но не обнаружил увеличения скорости, например. LinkedList<Matrix<double>>
. Было интересное упражнение.
person
Guy Coder
schedule
02.02.2017
int*int*int
- person Anton Schwaighofer   schedule 02.02.2017