Bir sinir ağı primerleri tanıyabilir mi?


26

Arka fon

İlkelliği tanımak (yapay) sinir ağları için uygun değil gibi görünüyor. Bununla birlikte, evrensel yaklaşım teoremi , sinir ağlarının herhangi bir sürekli işlevi yaklaştırabildiğini belirtir, bu nedenle özellikle arzu edilen herhangi bir sonlu destekli işlevi temsil etmek mümkün olmalıdır. Öyleyse ilk milyon sayıdaki tüm asalları tanımaya çalışalım.

Daha doğrusu, çünkü bu bir programlama web sitesi, hadi 2 ^ 20 = 1,048,576. Bu eşiğin altındaki primer sayısı 82,025 veya kabaca% 8'dir.

Meydan okuma

Bir sinir ağının ne kadar küçük olduğunu, 20-bit tam sayıların tümünü asal olarak mı yoksa asal olarak mı doğru şekilde sınıflandırdığını bulabilirsiniz?

Bu zorluğun amaçları doğrultusunda, bir sinir ağının büyüklüğü onu temsil etmek için gereken toplam ağırlık ve önyargı sayısıdır.

ayrıntılar

Amaç en aza indirgemek , açık ve net bir sinir ağının boyutunu .

Ağınıza giriş, 0s ve 1s ile veya alternatif olarak -1s ve + 1s ile temsil edilen bir tamsayı için ayrı ayrı bitler içeren bir vektör 20 olacaktır. Bunların sırası, ilk önce en anlamlı bit veya en az anlamlı bit olabilir.

Ağınızın çıktısı tek bir sayı olmalıdır; öyle ki, bazı kesimlerin üzerinde giriş asal olarak kabul edilir ve aynı kesimin altında giriş asal değil olarak kabul edilir. Örneğin, pozitif asal anlamına gelebilir (ve negatif asal değil) veya alternatif olarak 0.5'ten büyük asal olabilir (ve 0.5 den asal değil).

Ağ, tüm 2 ^ 20 = 1,048,576 olası girişlerde% 100 doğru olmalıdır. Yukarıda bahsedildiği gibi, bu aralıkta 82.025 priming olduğuna dikkat edin. (Her zaman "asal değil" çıktısının% 92 kesin olduğunu gösterir.)

Standart sinir ağı terminolojisi açısından, buna muhtemelen uygunluk denir . Başka bir deyişle, amacınız mükemmel astarlara uymak. Kullanılabilecek diğer bir deyişle "eğitim seti" ve "test seti" aynıdır.

Bu zorluk "eğitilebilir" veya "öğrenilebilir" parametrelerin sayısını dikkate almaz. Gerçekten de, ağınızın kodlanmış ağırlıklar içermesi muhtemeldir ve aşağıdaki örnek tamamen kodlanmıştır. Bunun yerine, tüm ağırlıklar ve önyargılar parametreler olarak kabul edilir ve sayılır.

Sinir ağınızı eğitmek veya oluşturmak için gereken kodun uzunluğu puanınızla ilgili değildir, ancak ilgili kodu göndermek kesinlikle takdir edilir.

Temel

Temel olarak, toplam 82.025 primi 1.804.551 toplam ağırlık ve önyargı ile "ezberlemek" mümkündür .

Aşağıdaki kodun bir çok şeyi içerdiğine dikkat edin: bir çalışma örneği, çalışma testi kodu, bilinen bir sinir ağı kitaplığı kullanan bir sinir ağı çalışma tanımı, "sabit kodlanmış" (veya en azından "eğitimli" olmayan) sinir ağı, ve çalışan bir skor ölçümü.

import numpy as np

bits = 20

from keras.models import Sequential
from keras.layers import Dense

from sympy import isprime

# Hardcode some weights
weights = []
biases  = []
for n in xrange(1<<bits):
    if not isprime(n):
        continue
    bit_list = [(n / (1 << i))%2 for i in xrange(bits)]
    weight = [2*bit - 1 for bit in bit_list]
    bias   = - (sum(bit_list) - 1)
    weights.append(weight)
    biases .append(bias)
nprimes = len(biases)
weights1 = np.transpose(np.array(weights))
biases1  = np.array(biases )
weights2 = np.full( (nprimes,1), 1 )
biases2  = np.array( [0] )

model = Sequential()
model.add(Dense(units=nprimes, activation='relu', input_dim=bits, weights=[weights1, biases1]))
model.add(Dense(units=1, activation='relu', weights=[weights2, biases2]))
print "Total weights and biases: {}".format( np.size(weights1) + np.size(weights2) + np.size(biases1) + np.size(biases2) )

# Evaluate performance
x = []
y = []
for n in xrange(1<<bits):
    row = [(n / (1 << i))%2 for i in xrange(bits)]
    x.append( row )
    col = 0
    if isprime(n):
        col = 1
    y.append( col )
x = np.array(x)
y = np.array(y)

model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['accuracy'])

loss, accuracy = model.evaluate(x, y, batch_size=256)
if accuracy == 1.0:
    print "Perfect fit."
else:
    print "Made at least one mistake."

Bir sinir ağı nedir?

Bu zorluğun amaçları doğrultusunda, (yapay) bir sinir ağının dar fakat kesin bir tanımını yazabiliriz. Bazı dış okumalar için Vikipedi'yi yapay sinir ağları , feedforward sinir ağları , çok katmanlı algılayıcı ve etkinleştirme işlevi hakkında öneriyorum .

Bir ileri beslemeli sinir ağı topluluğudur katmanları nöronların. Katman başına nöron sayısı, girdi katmanında 20 nöron, bir veya daha fazla gizli katmandaki bazı nöronlar ve çıkış katmanında 1 nöronla değişmektedir. (En az bir gizli katman olması gerekir, çünkü primerler ve primerler değil bit modellerine göre doğrusal olarak ayrılmazlar.) Yukarıdaki temel örnekte, katmanların boyutları [20, 82025, 1].

Giriş nöronlarının değerleri girdi tarafından belirlenir. Yukarıda tarif edildiği gibi, bu, 0 ila 2 ^ 20 arasında bir sayının bitlerine karşılık gelen 0s ve 1s veya benzer şekilde -1s ve + 1s olacaktır.

Çıkış katmanı da dahil olmak üzere her bir katmanın nöronlarının değerleri önceden kattan belirlenir. İlk önce, tamamen bağlı veya yoğun bir şekilde doğrusal bir işlev uygulanır . Böyle bir işlevi temsil etmenin bir yöntemi bir ağırlık matrisi kullanmaktır. Örneğin, taban çizgisinin ilk iki katı arasındaki geçişler 82025 x 20 matris ile gösterilebilir. Ağırlıkların sayısı, bu matristeki, örneğin 1640500'deki girdilerin sayısıdır. Daha sonra, her girişin eklenmiş (ayrı) bir önyargı terimi vardır. Bu bir vektörle gösterilebilir, örneğin bizim durumumuzda 82025 x 1 matris. Önyargı sayısı giriş sayısıdır, örneğin 82025. (Ağırlıklar ve önyargıların birlikte bir afin doğrusal işlevi tanımladığını unutmayın .)

Bir ağırlık veya yanlılık sıfır olsa bile sayılır. Bu dar tanımın amaçları açısından, önyargılar sıfır olsa bile ağırlık olarak sayılır. Temel örnekte, yalnızca iki farklı ağırlığın (+1 ve -1) kullanıldığını (ve sadece biraz daha belirgin önyargıların) olduğunu unutmayın; Bununla birlikte, büyüklüğü bir milyondan fazladır, çünkü tekrarlama hiçbir şekilde skor ile yardımcı olmuyor.

Son olarak, etkinleştirme işlevi adı verilen doğrusal olmayan bir işlev , bu afin doğrusal işlevinin sonucuna giriş olarak uygulanır. Bu dar tanımın amaçları için, evcil aktivasyon fonksiyonları relu , tanh ve sigmoid . Tüm katman aynı etkinleştirme işlevini kullanmalıdır.

Temel örnekte, ağırlık sayısı 20 * 82025 + 82025 * 1 = 1722525 ve önyargı sayısı 82025 + 1 = 82026, toplam 1722525 + 82026 = 1804551'dir. Sembolik bir örnek olarak, eğer varsa bir kat daha ve kat boyutları bunun yerine [20, a, b, 1], daha sonra ağırlık sayısı 20 x a + a * b + b * 1 olur ve önyargı sayısı bir + b + 1 olur.

Sinir ağının Bu tanım dahil birçok çerçeveler tarafından iyi desteklenir keras , scikit-öğrenme ve Tensorflow . Keras, yukarıdaki temel örnekte, esasen aşağıdaki gibi kod kullanılarak kullanılır:

from keras.models import Sequential
model = Sequential()
from keras.layers import Dense
model.add(Dense(units=82025, activation='relu', input_dim=20, weights=[weights1, biases1]))
model.add(Dense(units=1, activation='relu', weights=[weights2, biases2]))
score = numpy.size(weights1) + numpy.size(biases1) + numpy.size(weights2) + numpy.size(biases2)

Ağırlıklar ve önyargı matrisleri numpy dizileri ise, numpy.size size doğrudan giriş sayısını söyleyecektir.

Başka tür sinir ağları var mı?

Sinir ağının tek, kesin bir tanımını yapmak ve bu zorluğun amaçları için puan almak istiyorsanız, lütfen önceki bölümdeki tanımı kullanın. “Herhangi bir fonksiyonun” doğru yola baktığını ve parametrelerinin olmadığı bir sinir ağı olduğunu düşünüyorsanız, lütfen önceki bölümdeki tanımı kullanın.

Daha özgür bir ruhsan, daha fazlasını keşfetmeni tavsiye ederim. Belki de cevabınız dar zorluklara katılmaz, ama belki daha çok eğlenirsiniz. Deneyebileceğiniz diğer fikirler arasında daha fazla egzotik aktivasyon işlevi, tekrarlayan sinir ağları (her seferinde bir bit okuyarak), evrişimli sinir ağları, daha egzotik mimariler, softmax ve LSTM'ler (!) Bulunur. Herhangi bir standart etkinleştirme işlevini ve herhangi bir standart mimariyi kullanabilirsiniz. "Standart" sinir ağı özelliklerinin serbestçe tanımlanması, bu sorunun gönderilmesinden önce arşivde yayınlanan her şeyi içerebilir.


Bu ağırlıklar ne tür tipleridir? Genellikle insanlar yüzer kullanıyorlar, diğer sayısal türleri kullanabilir miyiz? örneğin daha az, daha fazla veya sınırsız hassasiyet türleri.
Buğday Sihirbazı

@ SriotchilismO'Zaic: Dar tanımın amaçları açısından, tüm ağırlıklar ve ara değerler için yüzer ve çift (IEEE tek ve çift hassas kayan nokta gerçek sayıları) ile sınırlandırmanın mantıklı olduğunu düşünüyorum. (Bazı uygulamalarda hassas diğer miktarda kullanabilir bu not, ancak - örneğin 80 bit -. Değerlendirme sırasında)
A Rex

Bu soruyu seviyorum ama hayal kırıklığına uğradım, yeterli eğitim süresiyle bulmak için daha küçük bir sinir ağı yok.
Anush

Yanıtlar:


13

Deneme bölümü: toplam 59407, 6243 katman, toplamda 16478 nöron

Net üreten ve doğrulayan bir Python programı olarak verilir. trial_divisionNasıl çalıştığının bir açıklaması için açıklamalara bakın . Doğrulama oldukça yavaş (saatlerce ölçülen çalışma süresi gibi): PyPy veya Cython kullanmanızı öneririz.

αmax(0,α)

Eşik 1'dir: yukarıdaki asal olan herhangi bir şey, aşağıdaki herhangi bir şey bileşik veya sıfırdır ve 1'in bir çıktısını veren tek girdi 1'dir.

#!/usr/bin/python3

import math


def primes_to(n):
    ps = []
    for i in range(2, n):
        is_composite = False
        for p in ps:
            if i % p == 0:
                is_composite = True
                break
            if p * p > i:
                break
        if not is_composite:
            ps.append(i)
    return ps


def eval_net(net, inputs):
    for layer in net:
        inputs.append(1)
        n = len(inputs)
        inputs = [max(0, sum(inputs[i] * neuron[i] for i in range(n))) for neuron in layer]
    return inputs


def cost(net):
    return sum(len(layer) * len(layer[0]) for layer in net)


def trial_division(num_bits):
    # Overview: we convert the bits to a single number x and perform trial division.
    # x is also our "is prime" flag: whenever we prove that x is composite, we clear it to 0
    # At the end x will be non-zero only if it's a unit or a prime, and greater than 1 only if it's a prime.
    # We calculate x % p as
    #     rem = x - (x >= (p << a) ? 1 : 0) * (p << a)
    #     rem -= (rem >= (p << (a-1)) ? 1) : 0) * (p << (a-1))
    #     ...
    #     rem -= (rem >= p ? 1 : 0) * p
    #
    # If x % p == 0 and x > p then x is a composite multiple of p and we want to set it to 0

    N = 1 << num_bits
    primes = primes_to(1 + int(2.0 ** (num_bits / 2)))

    # As a micro-optimisation we exploit 2 == -1 (mod 3) to skip a number of shifts for p=3.
    # We need to bias by a multiple of 3 which is at least num_bits // 2 so that we don't get a negative intermediate value.
    bias3 = num_bits // 2
    bias3 += (3 - (bias3 % 3)) % 3

    # inputs: [bit0, ..., bit19]
    yield [[1 << i for i in range(num_bits)] + [0],
           [-1] + [0] * (num_bits - 1) + [1],
           [0] * 2 + [-1] * (num_bits - 2) + [1],
           [(-1) ** i for i in range(num_bits)] + [bias3]]

    for p in primes[1:]:
        # As a keyhole optimisation we overlap the cases slightly.
        if p == 3:
            # [x, x_is_even, x_lt_4, x_reduced_mod_3]
            max_shift = int(math.log((bias3 + (num_bits + 1) // 2) // p, 2))
            yield [[1, 0, 0, 0, 0], [0, 1, -1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, -1, p << max_shift]]
            yield [[1, -N, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, -1, 1]]
            yield [[1, 0, 0, 0], [0, 1, -p << max_shift, 0]]
        else:
            # [x, x % old_p]
            max_shift = int(num_bits - math.log(p, 2))
            yield [[1, 0, 0], [1, -N, -p_old], [-1, 0, p << max_shift]]
            yield [[1, -N, 0, 0], [0, 0, -1, 1]]
            yield [[1, 0, 0], [1, -p << max_shift, 0]]

        for shift in range(max_shift - 1, -1, -1):
            # [x, rem]
            yield [[1, 0, 0], [0, 1, 0], [0, -1, p << shift]]
            yield [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 1]]
            yield [[1, 0, 0, 0], [0, 1, -p << shift, 0]]
        # [x, x % p]
        p_old = p

    yield [[1, 0, 0], [1, -N, -p]]
    yield [[1, -N, 0]]


def validate_primality_tester(primality_tester, threshold):
    num_bits = len(primality_tester[0][0]) - 1
    primes = set(primes_to(1 << num_bits))
    errors = 0
    for i in range(1 << num_bits):
        expected = i in primes
        observed = eval_net(primality_tester, [(i >> shift) & 1 for shift in range(num_bits)])[-1] > threshold
        if expected != observed:
            errors += 1
            print("Failed test case", i)
        if (i & 0xff) == 0:
            print("Progress", i)

    if errors > 0:
        raise Exception("Failed " + str(errors) + " test case(s)")


if __name__ == "__main__":
    n = 20

    trial_div = list(trial_division(n))
    print("Cost", cost(trial_div))
    validate_primality_tester(trial_div, 1)

Bir kenara, yeniden

evrensel yaklaşım teoremi, sinir ağlarının herhangi bir sürekli işlevi yaklaştırabileceğini belirtir.

max(0,1ai)max(0,1+(ai1))ancak girişlerinin 0 veya 1 olması garanti edilirse doğru çalışır ve daha büyük tamsayılar verebilir. Bir katmanda çeşitli diğer kapılar mümkündür, ancak NOR kendiliğinden Turing-complete'dur, bu nedenle ayrıntıya girmenize gerek yoktur.


Bir kenara ek olarak, deneme bölümünü denemeden önce bir Euler testi üzerinde çalışmaya başladım, çünkü daha verimli olacağını düşündüm, ama bir sayıyı (7 en iyi adaydı) gücüne (x- (x mod 2) yükseltmek ) x çarpımını izleyen 38 çarpım ve x x çarpımı gerektirecek ve 20 bitlik sayıları 1135 ile çarpmak için bulduğum en iyi ağ, bu yüzden rekabetçi olmayacak.
Peter Taylor

7

Skor 984314, 82027 kat, toplam 246076 nöron

Analizi basitleştiren ReLU etkinleştirme işlevini kullanırsak, şeyleri tam sayılarda tutabiliriz.

xx=a

  1. gea=(xa)+lea=(x+a)+
  2. eqa=(gealea+1)+eqa1x=a0

x

ge2=(x2)+le2=(x+2)+

accum2=(ge2le2+1)+ge3=(ge2(32))+le3=(ge2+(32))+

accum3=(221accum2ge3le3+1)+ge5=(ge3(53))+le5=(ge3+(53))+

accum5=(221accum3ge5le5+1)+ge7=(ge5(75))+le7=(-ge5+(7-5))+. Maliyet (3 + 1) * 3 = 12.

...

Katman 82026: çıkışlar accum1048571=(221accum1048559-ge1048571-le1048571+1)+, ge1048573=(ge1048571-(1048573-1048571))+, le1048573=(-ge1048571+(1048573-1048571))+. Maliyet (3 + 1) * 3 = 12.

Katman 82027: çıkışlar accum1048573=(221accum1048571-ge1048573-le1048573+1)+. Maliyet (3 + 1) * 1 = 4.

Eşik 0'dır. Çiftler ile çalışıyorsanız, taşma + oldukça mümkün, ancak bu kurallara uygun olarak mükemmel görünüyor.

Puan (82026 - 3) * 12 + 21 + 4 + 9 + 4.


Güzel. Anladığım kadarıyla, bu aynı zamanda primerleri “ezberler”, ancak “paralel” değil, “sıralı” eşitliği test eder. (Alternatif olarak, taban çizgisinin bir devri gibidir.) İlk adım, bit deseninden derhal uzaklaşmak ve sadece gerçek tamsayının kendisiyle çalışmaktır. Sonuç olarak, eşitlik kontrolünde 20 kat ceza yoktur. Gönderdiğiniz için teşekkür ederiz
A. Rex

Üst simge artı nedir?
feersum

1
@feersum, bu soruya iliştirilen ReLU'daki Wikipedia sayfasından yazıyor. x+=maksimum(0,x)
Peter Taylor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.