Máy học Golf: Nhân


68

Tôi muốn đề xuất một loại thử thách chơi gôn khác cho cộng đồng này:

(Nhân tạo) Mạng nơ-ron là mô hình học máy rất phổ biến có thể được thiết kế và đào tạo để xấp xỉ bất kỳ chức năng nào (thường không biết). Chúng thường được sử dụng để giải quyết các vấn đề rất phức tạp mà chúng ta không biết cách giải quyết bằng thuật toán như nhận dạng giọng nói, một số loại phân loại hình ảnh, các tác vụ khác nhau trong các hệ thống lái xe tự trị, ... Đối với một mạng lưới thần kinh, hãy xem xét điều này tuyệt vời Wikipedia bài viết .

Vì đây là lần đầu tiên trong những gì tôi hy vọng sẽ là một loạt các thử thách chơi gôn máy, tôi muốn giữ mọi thứ đơn giản nhất có thể:

Trong ngôn ngữ và khung bạn chọn, thiết kế và huấn luyện một mạng nơ ron, được đưa ra (x1,x2) tính sản phẩm của họ x1x2 cho tất cả các số nguyên x1,x2 giữa (và bao gồm) 1010 .

Mục tiêu hoạt động

Để đủ điều kiện, mô hình của bạn không được sai lệch quá 0.5 so với kết quả chính xác trên bất kỳ mục nào trong số đó.

Quy tắc

Mô hình của bạn

  • phải là mạng thần kinh 'truyền thống' (giá trị của một nút được tính như một tổ hợp tuyến tính có trọng số của một số nút trong lớp trước theo sau là hàm kích hoạt),
  • chỉ có thể sử dụng các chức năng kích hoạt tiêu chuẩn sau:
    1. linear(x)=x ,
    2. softmax(x)i=exijexj ,
    3. seluα,β(x)={βx, if x>0αβ(ex1), otherwise ,
    4. softplus(x)=ln(ex+1) ,
    5. leaky-reluα(x)={x, if x<0αx, otherwise ,
    6. tanh(x) ,
    7. sigmoid(x)=exex+1 ,
    8. hard-sigmoid(x)={0, if x<2.51, if x>2.50.2x+0.5, otherwise ,
    9. ex
  • phải lấy (x1,x2) làm tupel / vector / list / ... của số nguyên hoặc số float làm đầu vào duy nhất của nó,
  • trả về câu trả lời dưới dạng một số nguyên, float (hoặc một thùng chứa phù hợp, ví dụ như một vectơ hoặc danh sách, có chứa câu trả lời này).

Câu trả lời của bạn phải bao gồm (hoặc liên kết đến) tất cả các mã cần thiết để kiểm tra kết quả của bạn - bao gồm các trọng số được đào tạo của mô hình của bạn.

Chấm điểm

Mạng thần kinh có số lượng trọng lượng nhỏ nhất (bao gồm cả trọng số sai lệch) sẽ thắng.

Thưởng thức!


9
Chào mừng đến với trang web! Tôi nghĩ rằng thách thức này có thể có lợi cho một thỏa thuận tốt từ một định nghĩa mạnh mẽ hơn về mạng lưới thần kinh. Có một vài điều ở đây 1) Sẽ rất tốt nếu bạn nói nó bằng ngôn ngữ chưa bao hàm kiến ​​thức về NN 2) Bạn thực sự nên liệt kê các chức năng kích hoạt trong bài đăng của mình thay vì liên kết với nguồn bên ngoài ( liên kết bên ngoài có thể thay đổi hoặc biến mất).
Phù thủy lúa mì

4
Chúng ta có thể tái sử dụng trọng lượng / sử dụng các lớp chập không? (Tôi khuyên bạn nên loại bỏ phần thưởng, vì nó không thêm bất cứ điều gì vào thử thách và chỉ làm mất tập trung vào mục tiêu chính.) Các trọng số được cho là có thật hay chúng có thể phức tạp?
flawr

4
Từ ngữ của bạn ngụ ý các nút từ lớp 3 không thể sử dụng đầu vào từ lớp 1. Có tốn một trọng lượng để có một nút lớp 2 chỉ đơn giản là làm f(x) = xđể chuyển tiếp đầu vào của nó không?
Grimy

4
Cần có một liên kết ở cột bên phải tới Sandbox, được tạo ra một cách rõ ràng để khắc phục các loại vấn đề này trước khi câu hỏi thậm chí được đăng lên trang web chính. Và triết lý mạng là tốt hơn là đóng một câu hỏi, sửa nó và mở lại nó hơn là nhận được một loạt các câu trả lời sẽ không có ý nghĩa gì sau khi câu hỏi được sửa chữa hoặc sẽ hạn chế chặt chẽ những thay đổi có thể được thực hiện cho câu hỏi .
Peter Taylor

7
Không có gì. Những loại vấn đề này được phát hiện bởi kinh nghiệm nhiều năm khi thấy người khác mắc lỗi tương tự. Một số sự mơ hồ trượt qua hộp cát, nhưng nhiều người khác bị bắt ở đó. Và điều này chắc chắn đã bị bắt, bởi vì như đã nêu trong nhận xét đầu tiên của tôi, chúng tôi có chính xác những vấn đề tương tự với một câu hỏi mạng thần kinh hai tháng trước.
Peter Taylor

Câu trả lời:


37

21 13 11 9 trọng lượng

Điều này dựa trên danh tính phân cực của các dạng song tuyến mà trong trường hợp thực một chiều làm giảm nhận dạng đa thức:

xy=(x+y)2(xy)24

Vì vậy, y1chỉ cần tính toán [x+y, x-y]bằng cách sử dụng một phép biến đổi tuyến tính và y3chỉ là giá trị tuyệt đối của y1bước tiền xử lý cho bước tiếp theo: Sau đó, phần "cứng" là tính toán các hình vuông mà tôi sẽ giải thích bên dưới, và sau đó chỉ tính toán một sự khác biệt và chia tỷ lệ lại là một hoạt động tuyến tính.

s{0,1,2,,20}0.5

approx_square(x)=i=02wiexp(0.0001ix)

W2=(wi)i0.02

function p = net(x)
% 9 weights
one = 1; 
mone =-1;
zero = 0;
fourth = 0.25;
W1 = [1e-4, 2e-4];
W2  = [-199400468.100687;99700353.6313757];
b2 = 99700114.4299316;
leaky_relu = @(a,x)max(a*x,x); 


% Linear
y0 = [one, one; one, mone] * x;

% Linear + ReLU
y1 = mone * y0;
y2 = [leaky_relu(zero, y0), leaky_relu(zero, y1)];

% Linear
y3 = y2 * [one; one];

% Linear + exp
y4 = exp(y3 * W1); 

% Linear + Bias
y5 =  y4 * W2 + b2;

% Linear
y6 = [one, mone]*y5;
p = y6 * fourth;

end

Hãy thử trực tuyến!


Tôi nghĩ rằng mã kiểm tra của bạn trong phần chân trang của liên kết TIO bỏ lỡ một ứng dụng abs. Nhưng dù sao mọi thứ cũng tốt.
Christian Sievers

@ChristianSievers Cảm ơn, tôi đã cập nhật liên kết TIO!
flawr

Tôi không phải là một chuyên gia về NN, vì tò mò, làm thế nào để tính trọng lượng? y0cần 4, y1cần 2, y3cần 2, y4cần 1, y5cần 1 và y6cần 2. Đó là 12?
Margaret Bloom

3
@MargaretBloom Vâng, điều này thực sự hơi bất thường, nhưng OP cho biết trong các bình luận rằng chúng ta có thể sử dụng lại trọng lượng và chỉ phải đếm chúng một lần, ngay cả khi chúng ta sử dụng cùng một trọng lượng nhiều lần. Vì vậy, tất cả các trọng số tôi đang sử dụng được xác định trong phần đầu tiên của hàm.
flawr

31

7 trọng lượng

eps = 1e-6
c = 1 / (2 * eps * eps)

def f(A, B):
	e_s = exp(eps * A + eps * B)  # 2 weights, exp activation
	e_d = exp(eps * A - eps * B)  # 2 weights, exp activation
	return c * e_s + (-c) * e_d + (-1 / eps) * B  # 3 weights, linear activation

Hãy thử trực tuyến!

ϵex1+x+x22

ABeϵA+ϵBeϵAϵB2ϵ2Bϵ

ϵepsc


1
Không chắc chắn rằng điều này được tính là 'mạng lưới thần kinh truyền thống' (quy tắc số 1) nhưng rõ ràng là nó có thể được định dạng lại thành một, vì vậy tôi thấy không có vấn đề gì với điều đó. Giải pháp tốt đẹp!
Stefan Mesken

1
Bạn có thể xác định C = -B(1 trọng lượng) và sau đó có [e_s, e_d] = conv([A,B,C], [eps, eps])(2 trọng lượng) để tiết kiệm một trọng lượng :) (BTW: Cách tiếp cận rất thông minh!)
flawr

(Tôi quên thêm exp)
flawr

4
Bạn thậm chí có thể giảm xuống rất nhiều bằng cách sử dụng lại trọng lượng - bạn không phải tính cùng một trọng lượng nhiều lần.
flawr

2
@flawr Đó là một mẹo hay, nhưng tôi nghĩ rằng các khoản trợ cấp cho việc tích chập và sử dụng lại trọng số trong các bình luận làm cho điều này trở thành một thách thức khác mà tôi sẽ giữ câu trả lời này.
xnor

22

33 31 trọng lượng

# Activation functions
sub hard { $_[0] < -2.5 ? 0 : $_[0] > 2.5 ? 1 : 0.2 * $_[0] + 0.5 }
sub linear { $_[0] }

# Layer 0
sub inputA() { $a }
sub inputB() { $b }

# Layer 1
sub a15() { hard(5*inputA) }

# Layer 2
sub a8()  { hard(-5*inputA + 75*a15 - 37.5) }

# Layer 3
sub aa()  { linear(-5*inputA + 75*a15 - 40*a8) }

# Layer 4
sub a4()  { hard(aa - 17.5) }

# Layer 5
sub a2()  { hard(aa - 20*a4 - 7.5) }

# Layer 6
sub a1()  { linear(0.2*aa - 4*a4 - 2*a2) }

# Layer 7
sub b15() { hard(0.25*inputB - 5*a15) }
sub b8()  { hard(0.25*inputB - 5*a8) }
sub b4()  { hard(0.25*inputB - 5*a4) }
sub b2()  { hard(0.25*inputB - 5*a2) }
sub b1()  { hard(0.25*inputB - 5*a1) }

# Layer 8
sub output() { linear(-300*b15 + 160*b8 + 80*b4 + 40*b2 + 20*b1 - 10*inputA) }

# Test
for $a (-10..10) {
        for $b (-10..10) {
                die if abs($a * $b - output) >= 0.5;
        }
}

print "All OK";

Hãy thử trực tuyến!

Điều này không nhân dài trong nhị phân (sorta), và do đó trả về kết quả chính xác. Có thể tận dụng cửa sổ lỗi 0,5 để chơi golf thêm một số điều này, nhưng tôi không biết làm thế nào.

Các lớp 1 đến 6 phân tách đầu vào đầu tiên trong 5 "bit". Vì lý do chơi gôn, chúng tôi không sử dụng nhị phân thực tế. "Bit" đáng kể nhất có trọng số -15 thay vì 16 và khi đầu vào bằng 0, tất cả các "bit" là 0,5 (vẫn hoạt động tốt, vì nó giữ nguyên danh tính inputA = -15*a15 + 8*a8 + 4*a4 + 2*a2 + 1*a1).


1
Tôi đã mong đợi ai đó sẽ đưa ra một thuật toán nhân mã hóa cứng ANN. Nhưng tôi không nghĩ đó sẽ là phản hồi đầu tiên. Làm tốt! (Tôi cũng háo hức xem liệu bạn sẽ có thể loại bỏ thứ gì đó như thế này với bộ dữ liệu MNIST hay một số vấn đề ML khác, đáng tin cậy hơn: D.)
Stefan Mesken

14

43 trọng lượng

Hai giải pháp được đăng cho đến nay rất thông minh nhưng cách tiếp cận của chúng có thể sẽ không hiệu quả đối với các tác vụ truyền thống hơn trong học máy (như OCR). Do đó, tôi muốn gửi một giải pháp 'chung chung' (không có thủ thuật thông minh) cho nhiệm vụ này, hy vọng sẽ truyền cảm hứng cho những người khác để cải thiện nó và bị cuốn vào thế giới của máy học:

Mô hình của tôi là một mạng thần kinh rất đơn giản với 2 lớp ẩn được xây dựng trong TensorFlow 2.0 (nhưng bất kỳ khung nào khác cũng sẽ hoạt động tốt):

model = tf.keras.models.Sequential([
tf.keras.layers.Dense(6, activation='tanh', input_shape=(2,)),
tf.keras.layers.Dense(3, activation='tanh'),
tf.keras.layers.Dense(1, activation='linear')
])

Như bạn có thể thấy, tất cả các lớp đều dày đặc (điều chắc chắn là không tối ưu), chức năng kích hoạt là tanh (có thể thực sự ổn cho nhiệm vụ này), ngoại trừ lớp đầu ra, do tính chất của nhiệm vụ này, có chức năng kích hoạt tuyến tính.

Có 43 trọng lượng:

  • (2+1)6=18
  • (6+1)3=21
  • (3+1)1=4

1010

Tiếp theo, tôi đã tinh chỉnh chúng - tối ưu hóa cho độ lệch tối đa trên bất kỳ tác vụ nhân số nguyên nào. Thật không may, các ghi chú của tôi không hiển thị nhiều tinh chỉnh tôi đã kết thúc, nhưng nó rất nhỏ. Trong vùng lân cận 100 epoch trên 441 mẫu đào tạo đó, với cỡ lô là 441.

Đây là những trọng lượng tôi đã kết thúc với:

[<tf.Variable 'dense/kernel:0' shape=(2, 6) dtype=float32, numpy=
 array([[ 0.10697944,  0.05394982,  0.05479664, -0.04538541,  0.05369904,
         -0.0728976 ],
        [ 0.10571832,  0.05576797, -0.04670485, -0.04466859, -0.05855528,
         -0.07390639]], dtype=float32)>,
 <tf.Variable 'dense/bias:0' shape=(6,) dtype=float32, numpy=
 array([-3.4242163, -0.8875816, -1.7694025, -1.9409281,  1.7825342,
         1.1364107], dtype=float32)>,
 <tf.Variable 'dense_1/kernel:0' shape=(6, 3) dtype=float32, numpy=
 array([[-3.0665843 ,  0.64912266,  3.7107112 ],
        [ 0.4914808 ,  2.1569328 ,  0.65417236],
        [ 3.461693  ,  1.2072319 , -4.181983  ],
        [-2.8746269 , -4.9959164 ,  4.505049  ],
        [-2.920127  , -0.0665407 ,  4.1409926 ],
        [ 1.3777553 , -3.3750365 , -0.10507642]], dtype=float32)>,
 <tf.Variable 'dense_1/bias:0' shape=(3,) dtype=float32, numpy=array([-1.376577  ,  2.8885336 ,  0.19852689], dtype=float32)>,
 <tf.Variable 'dense_2/kernel:0' shape=(3, 1) dtype=float32, numpy=
 array([[-78.7569  ],
        [-23.602606],
        [ 84.29587 ]], dtype=float32)>,
 <tf.Variable 'dense_2/bias:0' shape=(1,) dtype=float32, numpy=array([8.521169], dtype=float32)>]

0.44350433910=90.443504

Mô hình của tôi có thể được tìm thấy ở đây và bạn cũng có thể dùng thử trực tuyến! trong môi trường Google Colab.


6

2 trọng lượng

ϵ>0

xyeϵx+ϵy+eϵxϵyeϵxϵyeϵx+ϵy4ϵ2.

ϵ=0.01

{±ϵ,±(4ϵ2)1}{±ϵ,(4ϵ3)1}±(4ϵ2)1=±ϵ(4ϵ3)1. Như tôi đã đề cập trong một nhận xét ở trên, mọi mạng lưới thần kinh có trọng lượng chính xác của máy có thể được đánh vào một mạng lưới thần kinh (rất lớn!) Chỉ với hai trọng số riêng biệt. Tôi đã áp dụng quy trình này để viết mã MATLAB sau:

function z=approxmultgolfed(x,y)

w1 = 0.1;   % first weight
w2 = -w1;   % second weight

k  = 250000;
v1 = w1*ones(k,1);
v2 = w2*ones(k,1);

L1 = w1*eye(2);
L2 = [ w1 w1; w2 w2; w1 w2; w2 w1 ];
L3 = [ v1 v1 v2 v2 ];
L4 = v1';

z = L4 * L3 * exp( L2 * L1 * [ x; y ] );

{±0.1}

Làm thế nào để thoát khỏi chỉ với 1 trọng lượng (!)

{±0.1}0.10.1

0.1x=wwx,

w100.110.5

{±10k}10k

(Có lẽ chúng ta nên sửa đổi cách ghi lại trọng lượng được sử dụng trong các thử thách chơi gôn thần kinh trong tương lai.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.