การเรียนรู้ของเครื่อง: การคูณ


68

ฉันต้องการเสนอความท้าทายด้านการเล่นกอล์ฟแบบอื่นให้กับชุมชนนี้:

(ประดิษฐ์) โครงข่ายประสาทเทียมเป็นรูปแบบการเรียนรู้ของเครื่องที่ได้รับความนิยมอย่างมากซึ่งสามารถออกแบบและฝึกอบรมให้ใกล้เคียงกับฟังก์ชั่นใด ๆ พวกเขากำลังมักจะใช้ในการแก้ปัญหาที่ซับซ้อนมากที่เราไม่ทราบวิธีการที่จะแก้ปัญหาอัลกอริทึมเช่นการรับรู้คำพูดบางชนิดของการจำแนกประเภทภาพงานต่างๆในระบบการขับขี่อิสระ ... สำหรับไพรเมอร์ในเครือข่ายประสาทการพิจารณาที่ยอดเยี่ยมนี้ บทความวิกิพีเดีย

เนื่องจากนี่เป็นครั้งแรกในสิ่งที่ฉันหวังว่าจะเป็นชุดของการเรียนรู้ทักษะการเล่นกอล์ฟฉันต้องการที่จะทำให้สิ่งต่าง ๆ เป็นไปอย่างง่ายดาย:

ในภาษาและกรอบที่คุณเลือกออกแบบและฝึกอบรมโครงข่ายประสาทเทียมที่กำหนดคำนวณผลิตภัณฑ์ของพวกเขาสำหรับจำนวนเต็มทั้งหมดระหว่าง (และรวมถึงและ )(x1,x2)x1x2x1,x21010

เป้าหมายประสิทธิภาพ

เพื่อให้มีคุณสมบัติโมเดลของคุณอาจไม่เบี่ยงเบนมากกว่าจากผลลัพธ์ที่ถูกต้องในรายการใด ๆ เหล่านั้น0.5

กฎระเบียบ

โมเดลของคุณ

  • จะต้องเป็น 'โครงข่ายประสาท' แบบดั้งเดิม '(ค่าของโหนดนั้นคำนวณเป็นชุดแบบเชิงเส้นแบบถ่วงน้ำหนักของบางโหนดในเลเยอร์ก่อนหน้าตามด้วยฟังก์ชันการเปิดใช้งาน)
  • อาจใช้ฟังก์ชันการเปิดใช้งานมาตรฐานต่อไปนี้เท่านั้น:
    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
  • ต้องใช้ไม่ว่าจะเป็น tupel / vector / list / ... ของจำนวนเต็มหรือลอยเป็นอินพุตเท่านั้น(x1,x2)
  • ส่งคืนคำตอบเป็นจำนวนเต็มลอย (หรือคอนเทนเนอร์ที่เหมาะสมเช่นเวกเตอร์หรือรายการที่มีคำตอบนี้)

คำตอบของคุณจะต้องมี (หรือลิงค์ไปยัง) รหัสทั้งหมดที่จำเป็นในการตรวจสอบผลลัพธ์ของคุณ - รวมถึงน้ำหนักที่ผ่านการฝึกอบรมของแบบจำลองของคุณ

เกณฑ์การให้คะแนน

เครือข่ายประสาทเทียมที่มีน้ำหนักน้อยที่สุด (รวมถึงน้ำหนักอคติ) จะเป็นผู้ชนะ

สนุก!


9
ยินดีต้อนรับสู่เว็บไซต์! ฉันคิดว่าความท้าทายนี้จะได้ประโยชน์จากข้อ จำกัด ที่แข็งแกร่งของเครือข่ายประสาท มีสองสามสิ่งที่นี่ 1) มันจะดีมากสำหรับคุณที่จะระบุไว้ในภาษาที่ไม่ได้บ่งบอกถึงความรู้เกี่ยวกับ NNs 2) คุณควรแสดงรายการฟังก์ชั่นการเปิดใช้งานในโพสต์ของคุณแทนที่จะเชื่อมโยงไปยังแหล่งภายนอก ลิงก์ภายนอกสามารถเปลี่ยนแปลงหรือหายไป)
ข้าวสาลี Wizard

4
เราสามารถนำน้ำหนัก / ใช้เลเยอร์ Convolutional กลับมาใช้ใหม่ได้ไหม? (ฉันขอแนะนำให้นำโบนัสออกเนื่องจากไม่ได้เพิ่มอะไรเลยกับความท้าทายและเบี่ยงเบนความสนใจไปจากเป้าหมายหลัก) น้ำหนักที่ควรจะเป็นจริงหรือพวกมันซับซ้อนหรือไม่?
ข้อบกพร่อง

4
ข้อความของคุณหมายถึงโหนดจากเลเยอร์ 3 ไม่สามารถใช้อินพุตจากเลเยอร์ 1 มีค่าน้ำหนักหรือไม่ที่จะมีโหนดเลเยอร์ 2 ทำf(x) = xเพื่อส่งต่ออินพุตหรือไม่
Grimy

4
ควรมีลิงก์ในคอลัมน์ด้านขวาไปยัง Sandbox ซึ่งสร้างขึ้นโดยชัดแจ้งเพื่อแก้ไขปัญหาประเภทนี้ก่อนที่คำถามจะโพสต์ที่ไซต์หลัก และปรัชญาเครือข่ายก็คือจะเป็นการดีกว่าที่จะปิดคำถามแก้ไขและเปิดใหม่กว่าจะได้รับคำตอบจำนวนมากซึ่งจะไม่สมเหตุสมผลหลังจากคำถามได้รับการแก้ไขหรือจะ จำกัด การเปลี่ยนแปลงที่อาจเกิดขึ้นกับคำถามอย่างแน่นหนา .
Peter Taylor

7
ไม่ใช่เลย. ปัญหาประเภทนี้ตรวจพบโดยประสบการณ์หลายปีในการมองเห็นคนอื่นทำผิดแบบเดียวกัน ความคลุมเครือบางอย่างส่งผ่านแซนด์บ็อกซ์ แต่มีอีกมากมายที่ติดอยู่ที่นั่น และสิ่งนี้จะถูกจับได้อย่างแน่นอนเพราะตามที่ระบุไว้ในความคิดเห็นแรกของฉันเรามีปัญหาเดียวกันกับคำถามโครงข่ายประสาทเมื่อสองเดือนที่แล้ว
Peter Taylor

คำตอบ:


37

21 13 11 9 น้ำหนัก

นี่คือพื้นฐานของการแยกโพลาไรเซชันของรูปแบบ bilinearซึ่งในกรณีจริงหนึ่งมิติจะลดความเป็นพหุนาม:

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

ดังนั้นy1เพียงคำนวณ[x+y, x-y]โดยใช้การแปลงเชิงเส้นและy3เป็นเพียงค่าสัมบูรณ์ของy1ขั้นตอนก่อนการประมวลผลสำหรับส่วนถัดไป: จากนั้นส่วน "ยาก" คือการคำนวณกำลังสองที่ฉันจะอธิบายด้านล่างและหลังจากนั้นคำนวณความแตกต่างและการปรับขนาด เป็นการดำเนินการเชิงเส้นอีกครั้ง

การคำนวณสี่เหลี่ยมผมใช้ชุดชี้แจงซึ่งควรจะถูกต้องสำหรับทุกจำนวนเต็มภายในรอบ0.5ชุดนี้เป็นของแบบฟอร์ม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

ลองออนไลน์!


ผมคิดว่าการตรวจสอบรหัสของคุณในส่วนท้ายของการเชื่อมโยง TIO absที่บอลเฉียงแอพลิเคชันของ แต่ทุกอย่างเรียบร้อยดีอยู่แล้ว
Christian Sievers

@ChristianSievers ขอบคุณฉันอัปเดตลิงค์ TIO!
ข้อบกพร่อง

ฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับ NN ออกมาจากความอยากรู้การนับน้ำหนักทำได้อย่างไร y0ต้องการ 4, y1ต้องการ 2, y3ต้องการ 2, y4ต้องการ 1, y5ต้องการ 1 และy6ต้องการ 2 นั่นคือ 12
Margaret Bloom

3
@MargaretBloom ใช่นี่เป็นเรื่องผิดปกติเล็กน้อย แต่ OP กล่าวในความคิดเห็นว่าเราสามารถนำน้ำหนักมาใช้ซ้ำได้และต้องนับครั้งเดียวแม้ว่าเราจะใช้น้ำหนักเดียวกันหลายครั้ง น้ำหนักทั้งหมดที่ฉันใช้ถูกกำหนดไว้ในส่วนแรกของฟังก์ชั่น
ข้อบกพร่อง

31

7 น้ำหนัก

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

ลองออนไลน์!

ใช้ความเท่าเทียมกันโดยประมาณต่อไปนี้สำหรับขนาดเล็กตามการขยายตัวของเทย์เลอร์ :ϵex1+x+x22

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

การเลือกขนาดเล็กพอทำให้เราอยู่ในขอบเขตข้อผิดพลาดที่ต้องการ โปรดทราบว่าและมีน้ำหนักคงที่ในรหัสϵepsc


1
ไม่แน่ใจว่านี่จะนับเป็น 'เครือข่ายประสาทแบบดั้งเดิม' (กฎ # 1) แต่เห็นได้ชัดว่ามันสามารถจัดรูปแบบใหม่เป็นหนึ่งดังนั้นฉันเห็นว่าไม่มีปัญหา ทางออกที่ดี!
Stefan Mesken

1
คุณสามารถกำหนดC = -B(1 น้ำหนัก) แล้วมี[e_s, e_d] = conv([A,B,C], [eps, eps])(2 น้ำหนัก) เพื่อบันทึกน้ำหนักเดียว :) (BTW: วิธีที่ฉลาดมาก!)
ข้อบกพร่อง

(ฉันลืมที่จะเพิ่มexp)
ข้อบกพร่อง

4
คุณสามารถลดน้ำหนักลงได้มากโดยการใช้ตุ้มน้ำหนักซ้ำ - คุณไม่ต้องนับน้ำหนักเดียวกันหลาย ๆ ครั้ง
ข้อบกพร่อง

2
@ flawr นั่นเป็นเคล็ดลับที่ดี แต่ฉันคิดว่าการอนุญาตให้มีการชักชวนและการใช้น้ำหนักซ้ำในความคิดเห็นทำให้สิ่งนี้เป็นความท้าทายที่แตกต่างกันมากจนฉันจะต้องรักษาคำตอบนี้ไว้
xnor

22

33 31 น้ำหนัก

# 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";

ลองออนไลน์!

นี่เป็นการคูณแบบยาวในไบนารี (sorta) และส่งกลับผลลัพธ์ที่แน่นอน มันน่าจะเป็นไปได้ที่จะใช้ประโยชน์จากข้อผิดพลาด 0.5 หน้าต่างเพื่อเล่นกอล์ฟนี้อีก แต่ฉันไม่แน่ใจว่าอย่างไร

เลเยอร์ 1 ถึง 6 แยกส่วนอินพุตแรกใน 5 "บิต" สำหรับเหตุผลในการตีกอล์ฟเราไม่ได้ใช้ไบนารีจริง "บิต" ที่สำคัญที่สุดมีน้ำหนัก -15 แทนที่จะเป็น 16 และเมื่ออินพุตคือ 0 "บิต" ทั้งหมดคือ 0.5 (ซึ่งยังคงทำงานได้ดีเนื่องจากมันรักษาเอกลักษณ์inputA = -15*a15 + 8*a8 + 4*a4 + 2*a2 + 1*a1)


1
ฉันคาดหวังว่าจะมีคนมาด้วยอัลกอริทึมการคูณ ANN-ified แบบฮาร์ดโค้ด แต่ฉันไม่คิดว่ามันจะเป็นการตอบสนองแรก ทำได้ดี! (ฉันยังอยากเห็นด้วยว่าคุณจะสามารถดึงสิ่งนี้ออกมาด้วยชุดข้อมูล MNIST หรือปัญหา ML อื่น ๆ ที่น่าเชื่อถือได้: D.)
Stefan Mesken

14

43 น้ำหนัก

โซลูชันทั้งสองที่โพสต์ไปนั้นฉลาดมาก แต่แนวทางของพวกเขาอาจไม่สามารถใช้กับงานแบบดั้งเดิมมากขึ้นในการเรียนรู้ของเครื่องจักร (เช่น OCR) ดังนั้นฉันต้องการส่ง 'ทั่วไป' (ไม่มีกลอุบายที่ฉลาด) ไปยังงานนี้ซึ่งหวังว่าจะเป็นแรงบันดาลใจให้คนอื่น ๆ พัฒนามันขึ้นมาและถูกดูดเข้าสู่โลกแห่งการเรียนรู้ของเครื่องจักร:

โมเดลของฉันเป็นโครงข่ายประสาทที่ง่ายมากโดยมีเลเยอร์ที่ซ่อนอยู่ 2 ชั้นที่สร้างขึ้นใน TensorFlow 2.0 (แต่กรอบงานอื่น ๆ ก็ใช้ได้เช่นกัน):

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')
])

อย่างที่คุณเห็นทุกชั้นมีความหนาแน่น (ซึ่งแน่นอนที่สุดไม่เหมาะสม) ฟังก์ชั่นการเปิดใช้งานคือ tanh (ซึ่งจริง ๆ แล้วอาจไม่เป็นไรสำหรับงานนี้) ยกเว้นชั้นเอาต์พุตที่เนื่องจากลักษณะของงานนี้ มีฟังก์ชั่นการเปิดใช้งานเชิงเส้น

น้ำหนัก 43 มี:

  • (2+1)6=18ระหว่างอินพุตและเลเยอร์ที่ซ่อนอยู่เป็นครั้งแรก
  • (6+1)3=21ระหว่างเลเยอร์ที่ซ่อนและ
  • (3+1)1=4เชื่อมต่อซ่อนสุดท้ายและเลเยอร์เอาท์พุท

น้ำหนักได้รับการฝึกอบรม (ด้วย adam optimizer) โดยวิธีการใส่ชั้น: ก่อนอื่นพวกเขาได้รับการติดตั้งเพื่อลดข้อผิดพลาด squarred เฉลี่ยไม่เพียง แต่ในการคูณจำนวนเต็มระหว่างถึงแต่จริง ๆ แล้วเกี่ยวกับอินพุตในพื้นที่ใกล้เคียง . สิ่งนี้ส่งผลให้เกิดการบรรจบกันที่ดีขึ้นมากเนื่องจากลักษณะของการไล่ระดับสีที่ลาดลง และมันมีสัดส่วนการฝึกอบรม 400 Epochs มูลค่า 57,600 ตัวอย่างต่อการฝึกอบรมแต่ละชุดใช้ขนาดชุดละ 321010

ต่อไปฉันปรับจูนพวกมันให้เหมาะที่สุดสำหรับการเบี่ยงเบนสูงสุดของงานคูณจำนวนเต็ม น่าเสียดายที่บันทึกย่อของฉันไม่แสดงการปรับแต่งที่ดีฉันทำเสร็จ แต่มันก็น้อยมาก ในละแวกที่มี 100 epochs จาก 441 ตัวอย่างการฝึกอบรมที่มีขนาดแบทช์ 441

นี่คือน้ำหนักที่ฉันได้รับ:

[<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)>]

ซึ่งแทบจะไม่บรรลุเป้าหมายประสิทธิภาพที่ระบุไว้ ค่าเบี่ยงเบนสูงสุดสิ้นสุดขึ้นเป็นเป็น witnessd โดย90.4435040.44350433910=90.443504

โมเดลของฉันสามารถพบได้ที่นี่และคุณสามารถลองออนไลน์ได้! ในสภาพแวดล้อมของ Google Colab


6

น้ำหนัก 2

ฉันได้รับแรงบันดาลใจจากคำตอบอื่น ๆ เพื่อประมาณตัวตนโพลาไรซ์ในวิธีที่แตกต่าง สำหรับอันมันจะเป็นอย่างนั้นϵ>0

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

มันเพียงพอที่จะรับสำหรับความท้าทายนี้ϵ=0.01

ที่เห็นได้ชัดการดำเนินงานสุทธิประสาทนี้จะใช้เวลาประมาณน้ำหนักใน\} น้ำหนักสี่อย่างนี้สามารถลงเล่นได้ถึงสามโดยแยกตัวประกอบ1} ดังที่ฉันได้กล่าวไว้ในความคิดเห็นข้างต้นทุก ๆ โครงข่ายประสาทที่มีน้ำหนักในความแม่นยำของเครื่องจักรนั้นสามารถนำไปรวมกับตาข่ายโครงข่าย (ขนาดใหญ่!) ด้วยน้ำหนักที่ต่างกันเพียงสองเส้นเท่านั้น ฉันใช้ขั้นตอนนี้เพื่อเขียนรหัส MATLAB ต่อไปนี้:{±ϵ,±(4ϵ2)1}{±ϵ,(4ϵ3)1}±(4ϵ2)1=±ϵ(4ϵ3)1

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 ] );

ทั้งหมดบอกสุทธิประสาทนี้ประกอบด้วย 1,250,010 น้ำหนักทั้งหมดที่อาศัยอยู่ใน\}{±0.1}

วิธีที่จะไปด้วยน้ำหนักเพียง 1 (!)

มันจะเปิดออกคุณสามารถจำลองสุทธิประสาทใด ๆ ที่มีน้ำหนักในกับสุทธิประสาทขนาดใหญ่ที่มีเพียงหนึ่งน้ำหนักคือ-0.1อันที่จริงการคูณด้วยสามารถนำมาใช้เป็น{±0.1}0.10.1

0.1x=wwx,

ที่เป็นเวกเตอร์คอลัมน์รายการทั้งหมดเท่ากับ-0.1สำหรับอวนประสาทที่น้ำหนักครึ่งหนึ่งเป็นค่าบวกการแปลงนี้จะสร้างตาข่ายประสาทที่ใหญ่กว่าเท่าw100.110.5

ทั่วไปที่เห็นได้ชัดของขั้นตอนนี้จะเปลี่ยนสุทธิประสาทใด ๆ ที่มีน้ำหนักในเป็นสุทธิประสาทขนาดใหญ่ที่มีน้ำหนักเดียวk} เมื่อรวมกับขั้นตอนในความคิดเห็นของฉันข้างต้นจึงถือได้ว่าโครงข่ายประสาททุกส่วนที่มีน้ำหนักความแม่นยำของเครื่องจักรสามารถเปลี่ยนเป็นโครงข่ายใยประสาทเดี่ยวน้ำหนักได้{±10k}10k

(บางทีเราควรปรับเปลี่ยนวิธีนำคะแนนน้ำหนักกลับมาใช้ใหม่ในความท้าทายของการเล่นกอล์ฟสุทธิในอนาคต)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.