Skip to content

Instantly share code, notes, and snippets.

@cronokirby
Created February 22, 2017 19:01
Show Gist options
  • Save cronokirby/257adc4612e57e2e956de20debbecd3f to your computer and use it in GitHub Desktop.
Save cronokirby/257adc4612e57e2e956de20debbecd3f to your computer and use it in GitHub Desktop.
defmodule Linear do
@moduledoc """
Various useful functions for linear algebra operations
"""
@doc ~S"""
Zips every element in a, with every element in b, applying a function
at the same time
## Examples
iex> Linear.zip_with([1, 2], [1, 2], &(&1 + &2)) |> Enum.to_list
[2, 4]
"""
def zip_with(enum1, enum2, func) do
Stream.zip(enum1, enum2)
|> Stream.map(fn {a, b} -> func.(a, b) end)
end
@doc """
Adds 2 vectors together
## Examples
iex> Linear.add([123, 34], [45, 67])
[168, 101]
"""
def add(vec1, vec2) do
zip_with(vec1, vec2, &(&1 + &2))
|> Enum.to_list
end
@doc """
Applies a linear transformation to a vector
## Examples
iex> Linear.mul([[1, 1], [2, 2]], [3, 4])
[7, 14]
"""
def mul(mat, vec) do
Enum.map(mat, fn row ->
zip_with(row, vec, &(&1 * &2))
|> Enum.sum
end)
end
@doc """
The sigmoid activation function
"""
def sigmoid(z) when is_list z do
Enum.map(z, &sigmoid/1)
end
def sigmoid(z) do
1 / (1 + :math.exp(-z))
end
end
defmodule Network do
alias Statistics.Distributions.Normal
import Linear
@moduledoc """
A basic CNN used for image recognition
"""
defmodule State do
defstruct [:layers, :dimensions, :biases, :weights]
end
defp distribution({cols, rows}) do
for _ <- 1..rows do
Enum.map(1..cols, fn _ -> Normal.rand() end)
end
end
defp distribution(n) do
for _ <- 1..n, do: Normal.rand()
end
@doc """
Initialise a neural network, using standard distribution.
Takes a list of dimensions i.e. `[784, 15, 10]`
"""
def init(dimensions) do
inner_layers = Stream.drop(dimensions, 1)
%State{
layers: length(dimensions),
dimensions: dimensions,
biases: Enum.map(inner_layers, &distribution/1),
weights: Enum.slice(dimensions, 0..-2)
|> Stream.zip(inner_layers)
|> Enum.map(&distribution/1)
}
end
def feed_forward(network, input) do
Stream.zip(network.biases, network.weights)
|> Enum.reduce(input, fn {b, w}, a ->
mul(w, a) |> add(b) |> sigmoid
end)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment