sfondo
Riconoscere la primalità sembra inadeguato per le reti (artificiali) neurali. Tuttavia, il teorema di approssimazione universale afferma che le reti neurali possono approssimare qualsiasi funzione continua, quindi in particolare dovrebbe essere possibile rappresentare qualsiasi funzione supportata finitamente che si desidera. Quindi proviamo a riconoscere tutti i numeri primi tra i primi milioni di numeri.
Più precisamente, poiché si tratta di un sito Web di programmazione, passiamo a 2 ^ 20 = 1.048.576. Il numero di numeri primi al di sotto di questa soglia è 82.025 o circa l'8%.
Sfida
Quanto è piccola una rete neurale che classifica correttamente tutti i numeri interi a 20 bit come primi o non primi?
Ai fini di questa sfida, la dimensione di una rete neurale è il numero totale di pesi e distorsioni richiesti per rappresentarla.
Dettagli
L'obiettivo è ridurre al minimo le dimensioni di una singola rete neurale esplicita.
L'input per la tua rete sarà un vettore di lunghezza 20 contenente i singoli bit di un numero intero, rappresentato con 0 e 1 o in alternativa con -1 e + 1. L'ordinamento di questi può essere il primo bit più significativo o il primo bit meno significativo.
L'output della tua rete dovrebbe essere un singolo numero, in modo che al di sopra di un valore di soglia l'ingresso sia riconosciuto come primo e al di sotto dello stesso valore di soglia l'ingresso sia riconosciuto come non primo. Ad esempio, positivo potrebbe significare primo (e negativo non primo), o in alternativa maggiore di 0,5 potrebbe significare primo (e inferiore a 0,5 non primo).
La rete deve essere accurata al 100% su tutti i 2 ^ 20 = 1.048.576 ingressi possibili. Come accennato in precedenza, si noti che ci sono 82.025 numeri primi in questo intervallo. (Ne consegue che produrre sempre "non prime" sarebbe preciso al 92%.)
In termini di terminologia della rete neurale standard, questo verrebbe probabilmente chiamato overfitting . In altre parole, il tuo obiettivo è quello di adattare perfettamente i numeri primi. Altre parole che si potrebbero usare sono che "set di allenamento" e "set di test" sono gli stessi.
Questa sfida non considera il numero di parametri "allenabili" o "apprendibili". In effetti, è probabile che la tua rete contenga pesi codificati e l'esempio che segue è interamente codificato. Invece, tutti i pesi e le inclinazioni sono considerati parametri e vengono conteggiati.
La lunghezza del codice necessario per addestrare o generare la tua rete neurale non è rilevante per il tuo punteggio, ma la pubblicazione del relativo codice è sicuramente apprezzata.
Baseline
Come base, è possibile "memorizzare" tutti gli 82.025 numeri primi con 1.804.551 pesi e distorsioni totali.
Si noti che questo codice che segue comprende molte cose: un esempio funzionante, un codice di prova funzionante, una definizione funzionante di rete neurale che utilizza una libreria di rete neurale nota, una rete neurale "codificata" (o almeno non "addestrata"), e una misurazione funzionante del punteggio.
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."
Cos'è una rete neurale?
Ai fini di questa sfida, possiamo scrivere una definizione stretta ma precisa di una rete neurale (artificiale). Per alcune letture esterne, suggerisco Wikipedia su rete neurale artificiale , rete neurale feedforward , percettrone multistrato e funzione di attivazione .
Una rete neurale feedforward è una raccolta di strati di neuroni. Il numero di neuroni per strato varia, con 20 neuroni nello strato di input, un certo numero di neuroni in uno o più strati nascosti e 1 neurone nello strato di output. (Deve esserci almeno uno strato nascosto perché i numeri primi e non primi non sono separabili linearmente in base ai loro modelli di bit.) Nell'esempio di base sopra riportato, le dimensioni dei livelli sono [20, 82025, 1].
I valori dei neuroni di input sono determinati dall'input. Come descritto sopra, questo sarà 0s e 1s corrispondenti ai bit di un numero compreso tra 0 e 2 ^ 20, oppure -1s e + 1s in modo simile.
I valori dei neuroni di ogni strato successivo, incluso lo strato di output, sono determinati in anticipo dallo strato. Innanzitutto viene applicata una funzione lineare, in modo completamente connesso o denso . Un metodo per rappresentare una tale funzione sta usando una matrice di pesi . Ad esempio, le transizioni tra i primi due strati della linea di base possono essere rappresentate con una matrice 82025 x 20. Il numero di pesi è il numero di voci in questa matrice, ad esempio 1640500. Quindi ad ogni voce è stato aggiunto un termine di bias (separato). Questo può essere rappresentato da un vettore, ad esempio una matrice 82025 x 1 nel nostro caso. Il numero di distorsioni è il numero di voci, ad esempio 82025. (Notare che pesi e distorsioni descrivono insieme una funzione lineare affine ).
Viene conteggiato un peso o una distorsione anche se è zero. Ai fini di questa definizione ristretta, i pregiudizi contano come pesi anche se sono tutti zero. Si noti che nell'esempio di base vengono utilizzati solo due pesi distinti (+1 e -1) (e solo inclinazioni leggermente più distinte); tuttavia, la dimensione è superiore a un milione, perché la ripetizione non aiuta in alcun modo il punteggio.
Infine, una funzione non lineare chiamata funzione di attivazione viene applicata dal punto di vista dell'entrata al risultato di questa funzione lineare affine. Ai fini di questa definizione ristretta, le funzioni di attivazione consentite sono ReLU , tanh e sigmoid . L'intero livello deve utilizzare la stessa funzione di attivazione.
Nell'esempio di base, il numero di pesi è 20 * 82025 + 82025 * 1 = 1722525 e il numero di distorsioni è 82025 + 1 = 82026, per un punteggio totale di 1722525 + 82026 = 1804551. Come esempio simbolico, se ci fossero un altro livello e le dimensioni del livello erano invece [20, a, b, 1], quindi il numero di pesi sarebbe 20 * a + a * b + b * 1 e il numero di distorsioni sarebbe a + b + 1.
Questa definizione di rete neurale è ben supportata da molti framework, tra cui Keras , scikit-learn e Tensorflow . Keras viene utilizzato nell'esempio di base precedente, con il codice essenzialmente come segue:
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)
Se le matrici di pesi e di polarizzazione sono matrici intorpidite , numpy.size ti dirà direttamente il numero di voci.
Esistono altri tipi di reti neurali?
Se si desidera un'unica definizione precisa di rete neurale e punteggio ai fini di questa sfida, utilizzare la definizione nella sezione precedente. Se ritieni che "qualsiasi funzione" considerata nel modo giusto sia una rete neurale senza parametri , utilizza la definizione nella sezione precedente.
Se sei uno spirito più libero, ti incoraggio a esplorare ulteriormente. Forse la tua risposta non conta per la sfida ristretta , ma forse ti divertirai di più. Alcune altre idee che potresti provare includono funzioni di attivazione più esotiche, reti neurali ricorrenti (lettura di un bit alla volta), reti neurali convoluzionali, architetture più esotiche, softmax e LSTM (!). È possibile utilizzare qualsiasi funzione di attivazione standard e qualsiasi architettura standard. Una definizione liberale di funzionalità di rete neurale "standard" potrebbe includere qualsiasi cosa pubblicata su arxiv prima della pubblicazione di questa domanda.