我是Julia编程语言的新手,并且仍然会通过编写已经用Python编写的代码(或者至少在Python中试用过)来学习它。
有一篇文章解释了如何制作一个非常简单的神经网络:https : //medium.com/technology-invention-and-more/how-to-build-a-simple-neural-network-in-9-lines -of-python-code-cc8f23647ca1。
我使用Python尝试了本文中的代码,但工作正常。但是,我以前没有在Python中使用线性代数(例如点)。现在,我正在尝试将此代码转换为Julia,但是有些事情我无法理解。这是我的Julia代码:
using LinearAlgebra synaptic_weights = [-0.16595599, 0.44064899, -0.99977125]::Vector{Float64} sigmoid(x) = 1 / (1 + exp(-x)) sigmoid_derivative(x) = x * (1 -x) function train(training_set_inputs, training_set_outputs, number_of_training_iterations) global synaptic_weights for (iteration) in 1:number_of_training_iterations output = think(training_set_inputs) error = training_set_outputs .- output adjustment = dot(transpose(training_set_inputs), error * sigmoid_derivative(output)) synaptic_weights = synaptic_weights .+ adjustment end end think(inputs) = sigmoid(dot(inputs, synaptic_weights)) println("Random starting synaptic weights:") println(synaptic_weights) training_set_inputs = [0 0 1 ; 1 1 1 ; 1 0 1 ; 0 1 1]::Matrix{Int64} training_set_outputs = [0, 1, 1, 0]::Vector{Int64} train(training_set_inputs, training_set_outputs, 10000) println("New synaptic weights after training:") println(synaptic_weights) println("Considering new situation [1, 0, 0] -> ?:") println(think([1 0 0]))
我已经尝试将向量(如synaptic_weights)初始化为:
synaptic_weights = [-0.16595599 ; 0.44064899 ; -0.99977125]
但是,该代码无法正常工作。更确切地说,有三件事我不清楚:
我是否以正确的方式初始化向量和矩阵(它是否等同于原始作者在Python中所做的工作)?
在Python中,原始作者使用+和-运算符,其中一个操作数是向量,另一个是标量。我不确定这是否意味着在Python中按元素进行加法或减法。例如,Python中的(vector + scalar)是否等于Julia中的(vector。+ scalar)?
当我尝试运行上面的Julia代码时,出现以下错误:
ERROR: LoadError: DimensionMismatch("first array has length 12 which does not match the length of the second, 3.") Stacktrace: [1] dot(::Array{Int64,2}, ::Array{Float64,1}) at C:\Users\julia\AppData\Local\Julia-1.0.3\share\julia\stdlib\v1.0\LinearAlgebra\src\generic.jl:702 [2] think(::Array{Int64,2}) at C:\Users\Viktória\Documents\julia.jl:21 [3] train(::Array{Int64,2}, ::Array{Int64,1}, ::Int64) at C:\Users\Viktória\Documents\julia.jl:11 [4] top-level scope at none:0 in expression starting at C:\Users\Viktória\Documents\julia.jl:28
当功能think(inputs)尝试计算输入和synaptic_weights的点积时,会出现此错误。在这种情况下,输入为4x3矩阵,突触权重为3x1矩阵(向量)。我知道可以将它们相乘,结果将成为4x1矩阵(向量)。这不是说可以计算点积吗?
无论如何,该点乘积可以使用numpy包在Python中进行计算,因此我猜有某种方式也可以在Julia中进行计算。
对于点积,我还尝试创建一个以a和b作为参数的函数,并尝试计算其点积:首先,计算a和b的积,然后返回结果的总和。我不确定这是否是一个好的解决方案,但是当我使用该函数时,Julia代码没有产生预期的结果,因此我将其删除。
您能帮我提供这段代码吗?
这是调整为Julia的代码:
sigmoid(x) = 1 / (1 + exp(-x)) sigmoid_derivative(x) = x * (1 -x) think(synaptic_weights, inputs) = sigmoid.(inputs * synaptic_weights) function train!(synaptic_weights, training_set_inputs, training_set_outputs, number_of_training_iterations) for iteration in 1:number_of_training_iterations output = think(synaptic_weights, training_set_inputs) error = training_set_outputs .- output adjustment = transpose(training_set_inputs) * (error .* sigmoid_derivative.(output)) synaptic_weights .+= adjustment end end synaptic_weights = [-0.16595599, 0.44064899, -0.99977125] println("Random starting synaptic weights:") println(synaptic_weights) training_set_inputs = Float64[0 0 1 ; 1 1 1 ; 1 0 1 ; 0 1 1] training_set_outputs = Float64[0, 1, 1, 0] train!(synaptic_weights, training_set_inputs, training_set_outputs, 10000) println("New synaptic weights after training:") println(synaptic_weights) println("Considering new situation [1, 0, 0] -> ?:") println(think(synaptic_weights, Float64[1 0 0]))
有多个更改,因此如果您不清楚其中的一些内容,请提出要求,我将继续进行扩展。
我最重要的改变是:
不要使用全局变量,因为它们会显着降低性能
使所有数组具有Float64
元素类型
在几个需要进行广播的地方.
(例如,sigmoid
和sigmoid_derivative
函数的定义方式是希望它们得到一个数字作为参数,因此当我们调用它们时,.
会在它们的名称后添加它们以触发广播)
使用标准矩阵乘法*
代替dot
该代码的运行速度比Python中的原始实现快30倍。我没有为此代码压缩最大性能(现在可以避免很多分配),因为这需要重新编写其逻辑,我想您想直接重新实现。