刚了解 Flux.jl 两天,对这个东西有些疑问

model = Chain (
    Dense(2, 2, relu),
    Dense(2, 1, relu),
    softmax
)

data = []
for i in 1:10000
	print(i, " ")
	x = rand(2)
	if x[1] > x[2]
		push!(data, (x, [10.0]))
	else
		push!(data, (x, [0.0]))
	end
end
#目的是创建一个判断前后两个数大小的网络
ps = params(model)
opt = ADAMW()
Flux.train!(loss, ps, data, opt)
#发现没什么效果
model([233,666]) # 不管填什么,都只能出 1

求助

输入数据的格式有问题。
正确的输入方法参见

一组 x 是一个列向量。

X = rand(2, 100)
Y = []
for r in eachcol(X)
	if r[1] > r[2]
		push!(Y, 1.0)
	elseif r[1] == r[2]
		push!(Y, 0.5)
	else
		push!(Y, 0.0)
	end
end
data = [(X, Y)]

把这点改了还是有问题。

我照着

改了一个判断大小的,就可以用。

using Flux: Chain, Dense, params, crossentropy, onehotbatch, mse,
            ADAMW, train!, softmax
using Test

# Data preparation
function func(x, y)
    if x > y
        return "gt"
    elseif x < y
        return "lt"
    else
        return "eq"
    end
end
func(a::Array) = func.(a[1, :], a[2, :])

const LABELS = ["gt", "lt", "eq"];
@test func([1 0 1; 0 1 1]) == LABELS

raw_x = rand(2, 100);
raw_y = func(raw_x);

X = raw_x;
Y = onehotbatch(raw_y, LABELS);

# Model
m = Chain(Dense(2, 10), Dense(10, 3), softmax)
loss(x, y) = mse(m(x), y)
opt = ADAMW()

# Helpers
deepbuzz(x, y) = LABELS[argmax(m([x; y]))]
deepbuzz(a::Array) = deepbuzz.(a[1, :], a[2, :])

function monitor(e)
    print("epoch $(lpad(e, 4)): loss = $(round(loss(X,Y).data; digits=4)) | ")
    println(deepbuzz([1 0 1; 0 1 1]))
end

# Training
for e in 0:3000
    train!(loss, params(m), [(X, Y)], opt)
    if e % 100 == 0; monitor(e) end
end
epoch 2700: loss = 0.0088 | ["gt", "lt", "gt"]
epoch 2800: loss = 0.0085 | ["gt", "lt", "lt"]
epoch 2900: loss = 0.0082 | ["gt", "lt", "lt"]
epoch 3000: loss = 0.0079 | ["gt", "lt", "lt"]
julia> 

julia> deepbuzz([0,1])
1-element Array{String,1}:
 "lt"

julia> deepbuzz([0,-1])
1-element Array{String,1}:
 "gt"

julia> deepbuzz([0,0])
1-element Array{String,1}:
 "lt"

julia> deepbuzz([999,0])
1-element Array{String,1}:
 "gt"

julia> deepbuzz([999,5000])
1-element Array{String,1}:
 "lt"

julia> deepbuzz([3.15; 3.14])
1-element Array{String,1}:

你们俩用的model不一样

这里模型的输出是一个只有一个元素的向量,如果你理解softmax的实现的话,就明白为什么输出一直是1了。

正确的做法是像上面 @woclass 那样,生成一个onehot的编码作为label。

另外,一般不会在最后一层softmax前面加上relu作为激活函数。

1 个赞

Softmax函数 ,或称 归一化指数函数
\sigma(\mathbf{z})_j = \frac{e^{z_j}}{\sum_{k=1}^K e^{z_k}}

嗯,都归一化了。(