【问题标题】:porting python class to Julialang将 python 类移植到 Julialang
【发布时间】:2021-09-16 08:09:55
【问题描述】:

我看到 Julia 明确地不做类......我应该改用可变结构......我在这里走的是正确的道路吗?我将我的简单示例与官方通量库进行了比较,但无法收集如何像 python 对象一样引用self .. 是在函数中简单地将类型作为参数传递的最干净的方法吗??

Python

# Dense Layer
class Layer_Dense
    
    def __init__(self, n_inputs, n_neurons):
        self.weights = 0.01 * np.random.randn(n_inputs, n_neurons)
        self.biases = np.zeros((1, n_neurons))

    def forward(self, inputs):
        pass

到目前为止我的 JuliaLang 版本


mutable struct LayerDense
    num_inputs::Int64
    num_neurons::Int64
    weights
    biases
end


function forward(layer::LayerDense, inputs)
    layer.weights = 0.01 * randn(layer.num_inputs, layer.num_neurons)
    layer.biases = zeros((1, layer.num_neurons))
end

稠密层的通量库版本...对我来说看起来非常不同..我不知道他们在做什么或为什么..就像forward pass 调用在哪里,它在通量只是以层命名Dense???

来源:https://github.com/FluxML/Flux.jl/blob/b78a27b01c9629099adb059a98657b995760b617/src/layers/basic.jl#L71-L111

struct Dense{F, M<:AbstractMatrix, B}
  weight::M
  bias::B
  σ::F
  function Dense(W::M, bias = true, σ::F = identity) where {M<:AbstractMatrix, F}
    b = create_bias(W, bias, size(W,1))
    new{F,M,typeof(b)}(W, b, σ)
  end
end

function Dense(in::Integer, out::Integer, σ = identity;
               initW = nothing, initb = nothing,
               init = glorot_uniform, bias=true)

  W = if initW !== nothing
    Base.depwarn("keyword initW is deprecated, please use init (which similarly accepts a funtion like randn)", :Dense)
    initW(out, in)
  else
    init(out, in)
  end

  b = if bias === true && initb !== nothing
    Base.depwarn("keyword initb is deprecated, please simply supply the bias vector, bias=initb(out)", :Dense)
    initb(out)
  else
    bias
  end

  return Dense(W, b, σ)
end

【问题讨论】:

    标签: julia


    【解决方案1】:

    这相当于你在 Julia 中的 Python 代码:

    mutable struct Layer_Dense
        weights::Matrix{Float64}
        biases::Matrix{Float64}
    
        Layer_Dense(n_inputs::Integer, n_neurons::Integer) =
            new(0.01 * randn(n_inputs, n_neurons),
                zeros((1, n_neurons)))
    end
    
    forward(ld::Layer_Dense, inputs) = nothing
    

    这里有什么重要的:

    • 这里我只创建了一个inner constructor,因为不需要outer constructor;与您链接的 Flux.jl 代码相反,Dense 类型定义了内部和外部构造函数
    • 在 python 中forward 函数没有做任何事情,所以我在 Julia 中复制了它(你的 Julia 代码的工作方式有点不同);请注意,应该将对象的实例作为第一个参数传递给函数,而不是 self(并添加 ::Layer_Dense 类型签名,以便 Julia 知道如何正确调度它)
    • 类似地,在 Python 中,你只在类中存储 weightsbiases,我在 Julia 代码中反映了这一点;但是请注意,出于性能原因,最好提供Layer_Dense struct 的这两个字段的显式类型

    比如forward pass 调用在哪里

    在您共享的代码中,仅定义了 Dense 对象的构造函数。但是,在herehere 下面的行中,Dense 类型被定义为函子。 函子在here(一般)和here(更具体地针对您的用例)中进行了解释

    【讨论】:

    • 谢谢!我只是通过将num_neuronsnum_inputs 保存到变量来稍微修改我这边的答案.. 但这应该这样做.. 构造函数是我真正没有清楚地看到的东西。谢谢!
    • 关于 forward 什么都不做,是的,我正在关注一本使用 python 从头开始​​编写神经网络的书……但使用 JuliaLang 代替了对自己的挑战,希望能帮助我加深理解朱利安的
    • 请注意,如果您关心性能,则不要使用Matrix{Float64}Matrix{Float32} 在 CPU 上将快 2 倍,在 GPU 上快 32 倍。
    • @Oscar Smith 是对的。我想在答案中保存参数类型的复杂性,并在问题Float64 生成值中,请参阅docs.julialang.org/en/v1/manual/types/#Parametric-Types 以获取如何以一般方式定义结构的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2020-12-28
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多