O perceptrón desde cero: que calcula unha neurona
Constrúe un perceptrón en Python puro, mírao fallar con XOR e entende por que o seu teorema de converxencia promete éxito, non rapidez.
Nesta páxina
Hai unha cinta transportadora nunha fábrica. As pezas van pasando por ela, e alguén ten que decidir cales se envían e cales volven atrás. De cada peza mídense dous números: a súa anchura en milímetros e o seu peso en gramos. Esa é toda a información dispoñible.
A maneira obvia de automatizar isto é escribir a regra. Aceptar se a anchura é inferior a 22 milímetros. Funciona ata que o provedor cambia a aliaxe e os pesos se desprazan. Así que engades unha cláusula. Logo renegóciase a tolerancia e engades outra. Seis meses despois, a función ten corenta liñas, ninguén lembra por que está aí a liña 19 e a persoa que a escribiu xa marchou.
A outra maneira é o tema deste curso. Non escribes a regra. Escribes a forma da regra — un modelo con ocos — e deixas que os exemplos decidan que vai nos ocos. Esa inversión é todo o machine learning, e neste capítulo o modelo é tan pequeno como pode selo un modelo: dous números e un limiar.
Ao final terás escrito un perceptrón nunhas vinte liñas de Python, veralo ter éxito, veralo fallar e entenderás ambas as cousas. O ficheiro que escribes aquí non é un xoguete que se tira no seguinte capítulo: é o primeiro commit dun repositorio que remata, vinte e nove capítulos máis adiante, como un agent cun bucle de ferramentas e un modelo de permisos.
O modelo: unha suma ponderada e unha liña
Ligazón á sección: O modelo: unha suma ponderada e unha liñaUn perceptrón toma as medicións, multiplica cada unha por un número que controla, súmaas, engade un número máis e mira o signo.
Escribe as medicións dunha peza como un vector — anchura e peso. O perceptrón mantén un vector de pesos e un sesgo . A súa puntuación é
e a súa resposta é o signo desa puntuación: aceptar se , rexeitar en caso contrario.
Ese é todo o modelo. Todo o que o perceptrón chegará a saber sobre a fábrica vive en tres números.
Paga a pena deterse na xeometría, porque é a imaxe que segue funcionando durante os seguintes vinte e nove capítulos, mesmo cando as ecuacións deixen de caber nunha liña. O conxunto de puntos onde — onde o perceptrón está exactamente indeciso — é unha liña recta no plano. Nun lado a puntuación é positiva e todo se acepta; no outro é negativa e todo se rexeita. Para un perceptrón, aprender significa mover esa liña.
Dous feitos sobre esa liña despréndense directamente da álxebra, e ambos importan máis adiante:
- é perpendicular a ela. O vector de pesos non vai ao longo da fronteira; apunta a través dela, cara ao lado aceptado.
- desprázaa sen xirala. Sen un sesgo, a liña estaría obrigada a pasar pola orixe, o que nunha fábrica que mide milímetros e gramos sería unha restrición absurda: significaría que unha peza de anchura cero e peso cero está exactamente enriba da cerca.
A regra de aprendizaxe, e por que non precisa cálculo
Ligazón á sección: A regra de aprendizaxe, e por que non precisa cálculoO perceptrón comeza sen saber nada: e . Todas as puntuacións son cero, así que acepta todo.
Agora móstralle un exemplo de cada vez. Etiqueta as pezas aceptadas como e as rexeitadas como . Para cada exemplo, fai unha pregunta: saíu ben o signo? A forma compacta de escribir esa pregunta é comprobar se é positivo: se a etiqueta e a puntuación concordan no signo, o seu produto é positivo; se non concordan, é negativo.
Se a resposta é si, non cambies nada. Se a resposta é non, empurra un pouco:
Ese é todo o algoritmo, e paga a pena entender por que é o empurrón correcto en vez de memorizalo. Supón que unha peza debería terse aceptado () e a puntuación saíu negativa. Engadir a cambia a puntuación nesa mesma peza en
que é un número positivo. A puntuación da peza que acaba de clasificar mal sobe, que é a dirección na que tiña que ir. A regra non é unha heurística que alguén adiviñou; é o cambio máis pequeno que mellora de maneira demostrable o caso que ten diante. Por suposto, pode estragar outro caso, e por iso dás outra volta.
Fíxate no que falta. Non hai ningunha derivada. Non é un descoido, e é a primeira idea realmente importante do curso.
O que quererías diferenciar é o erro: o reconto de pezas mal clasificadas. Pero ese reconto é unha escaleira: queda plano en 4 mentres moves un pouco a liña, logo baixa a 3 no instante en que a liña cruza un punto. A súa derivada é cero case en todas partes e indefinida nos chanzos. O cálculo non ten de onde agarrarse. A regra do perceptrón traballa ao redor diso ao non pedir ningunha pendente: só pregunta "ben ou mal?" e móvese nunha dirección que pode xustificar xeometricamente.
Iso é unha solución real, e tamén é un camiño sen saída. No Capítulo 2 quereremos unha perda que veña dalgún sitio en vez de ser escollida, no Capítulo 4 un modelo que informe de como de seguro está, e no Capítulo 5 algo con máis dunha capa; e nada diso é alcanzable desde unha regra que só sabe "mal". Recuperar unha pendente útil é o que forza os dous capítulos seguintes. Pero o perceptrón pode facer algo que ningún dos seus sucesores pode: aprender sen cálculo ningún.
Escribilo
Ligazón á sección: EscribiloPython puro, sen NumPy. Listas e un bucle. NumPy chega no seguinte capítulo, onde a aritmética deixa de caber nun bucle que queiras ler; introducilo agora agocharía a aritmética detrás dunha biblioteca xusto no momento no que queres vela.
def score(w, b, x):
return w[0] * x[0] + w[1] * x[1] + b
def predict(w, b, x):
return 1 if score(w, b, x) >= 0 else -1
def train(data, epochs=200):
"""Returns (w, b, epoch_it_converged) — or None for the epoch if it never did."""
w, b = [0.0, 0.0], 0.0
for epoch in range(epochs):
mistakes = 0
for x, y in data:
if y * score(w, b, x) <= 0:
w[0] += y * x[0]
w[1] += y * x[1]
b += y
mistakes += 1
if mistakes == 0:
return w, b, epoch + 1
return w, b, NoneAs catro liñas destacadas son o algoritmo. Todo o demais é contabilidade.
E a cinta, con oito pezas medidas nela: catro que se enviaron e catro que volveron:
BELT = [
((18.0, 47.0), +1), ((19.5, 52.0), +1), ((20.2, 49.0), +1), ((21.0, 55.0), +1),
((24.0, 61.0), -1), ((25.5, 66.0), -1), ((23.0, 70.0), -1), ((26.0, 58.0), -1),
]
w, b, epoch = train(BELT, epochs=200)
print(epoch, w, b)Estas oito pezas son separables por unha liña recta: todas as pezas aceptadas están por debaixo de 22 mm e todas as rexeitadas teñen 23 mm ou máis. Unha cerca vertical nos 22 milímetros fai o traballo. Así que o perceptrón debería atopala.
Execútao:
None [-142.1, -13.0] 54.0Duascentas épocas, 454 correccións, e non converxeu. Os pesos son grandes e teñen o signo incorrecto. Algo vai mal; agás que non vai mal nada, e a razón é a cousa máis útil deste capítulo.
O teorema de converxencia, e o número que realmente che dá
Ligazón á sección: O teorema de converxencia, e o número que realmente che dáO perceptrón ten unha garantía, demostrada por Novikoff en 1962.1 Se os datos poden separarse por unha liña dalgunha maneira, o algoritmo fai como moito
correccións antes de deixar de facer ningunha, onde é o radio dos datos, a lonxitude do vector de exemplo máis longo, e é a marxe: a distancia desde o hiperplano separador ata o punto máis próximo no espazo aumentado onde o sesgo é unha terceira coordenada. Por iso centrar os datos o cambia aínda que a distancia en milímetros non cambie.
A garantía é incondicional e non menciona épocas, taxas de aprendizaxe nin sorte. Tampouco menciona o tempo, e esa omisión é a clave.
Metamos os nosos números. Medidos directamente a partir das oito pezas, co sesgo incorporado como unha característica constante:
| radio | marxe | límite | correccións feitas realmente | |
|---|---|---|---|---|
| milímetros e gramos en bruto | 73,69 | 0,045 | 2.633.550 | 29.870 |
| despois de restar a media | 12,82 | 0,989 | 168 | 1 |
O teorema nunca se violou. Executa a versión en bruto o tempo suficiente e converxe: na época 11.976, despois de 29.870 correccións, cómodamente dentro do seu límite de 2.633.550. E esa diferenza é precisamente a cuestión: o teorema acouta o peor caso, non o típico. Simplemente precisou sesenta veces máis épocas das que ninguén soportaría agardar.
A segunda fila son as mesmas oito pezas, as mesmas vinte liñas de código, con tres liñas engadidas para restar a anchura media e o peso medio a cada medición. Iso é todo. Ese é o cambio completo. Move a nube de puntos para que atravesen a orixe en vez de flotar arredor de (22, 57), e o efecto sobre o límite é un factor de quince mil, porque ambos termos melloran á vez: baixa de 74 a 13 porque os puntos xa non se miden desde unha orixe afastada, e sobe de 0,045 a 0,989 porque a marxe se mide contra un vector de pesos que xa non ten que cargar cun sesgo enorme para chegar aos datos.
mean_w = sum(x[0] for x, _ in BELT) / len(BELT) # 22.15
mean_g = sum(x[1] for x, _ in BELT) / len(BELT) # 57.25
CENTRED = [(((x[0] - mean_w), (x[1] - mean_g)), y) for x, y in BELT]
w, b, epoch = train(CENTRED, epochs=200)
print(epoch, w, b)2 [-4.15, -10.25] 1.0Converxeu en dúas épocas, tras corrixirse exactamente unha vez.
Hai aquí unha lección real, e non é "lembra normalizar as túas entradas", aínda que deberías facelo. É que unha garantía sobre se un algoritmo remata non che di nada sobre se estarás presente cando o faga, e que a distancia entre as dúas cousas adoita ser xeometría. Esta é a primeira aparición dun patrón que volverás atopar no Capítulo 6 coa inicialización, no Capítulo 10 cos calendarios de taxas de aprendizaxe e no Capítulo 13 coa cuantización: as matemáticas din que a cousa é posible, e a enxeñaría decide se é práctica. Un curso que che ensina só o teorema entrégache un modelo que adestra durante tres días e logo bótache a culpa.
Catro puntos, unha liña, ningunha solución
Ligazón á sección: Catro puntos, unha liña, ningunha soluciónAgora o fallo que puxo fin á primeira era das redes neuronais, e cabe en catro filas.
Esquece a fábrica. Toma dúas entradas que poden ser 0 ou 1, e pide que a resposta sexa cando exactamente unha delas é 1:
| 0 | 0 | |
| 0 | 1 | |
| 1 | 0 | |
| 1 | 1 |
Isto é XOR: ou exclusivo. Antes de seguir lendo, debuxa os catro puntos nun papel: tres cantos dun cadrado unidade e o cuarto. Marca os dous cantos diagonais e como aceptar, e e como rexeitar. Agora debuxa unha liña recta cos dous puntos aceptados nun lado e os dous rexeitados no outro.
Non podes. Non é que sexa difícil, nin que precises un algoritmo máis intelixente; é que esa liña non existe. Tres liñas de álxebra mostran por que. Se un perceptrón acertase os catro, entón ler as catro filas por orde dá
Suma as dúas desigualdades do medio: , polo tanto . A última di . Xuntas: , o que require , que require . E a primeira desigualdade di . Non hai tal , así que non hai tales pesos. Ningún perceptrón, con números calquera que sexan, clasifica XOR.
Execútao de todos modos, porque ver fallar un algoritmo vale máis que que che digan que vai fallar:
100 epochs -> converged=None w=[0.0, 0.0] b=0.0 correct=2/4
1,000 epochs -> converged=None w=[0.0, 0.0] b=0.0 correct=2/4
100,000 epochs -> converged=None w=[0.0, 0.0] b=0.0 correct=2/4Non diverxe, e tampouco se axita arredor dunha resposta decente. Cicla: percorre un bucle curto polo espazo de pesos e volve exactamente ao punto de partida, para sempre, acertando dous de catro, que é o que obterías ao azar. Cen mil épocas e cen son indistinguibles, porque o algoritmo non está facendo un progreso que unha execución máis longa poida rematar. Compárao coa cinta, que parecía atascada ás 200 épocas e en realidade avanzaba a moenda cara a unha resposta real. Desde fóra, as dúas cousas semellan parecidas durante os primeiros segundos. Distinguilas, sen o teorema, é imposible, e iso é outro argumento para coñecer o teorema.
O que Minsky e Papert dixeron realmente
Ligazón á sección: O que Minsky e Papert dixeron realmenteEn 1969 Marvin Minsky e Seymour Papert publicaron Perceptrons, un estudo matemático con extensión de libro sobre exactamente que pode e que non pode representar este modelo.2 XOR é o seu resultado máis citado, e a cita adoita usarse como acusación: que o libro matou a investigación en redes neuronais durante quince anos por rivalidade ou rancor.
As matemáticas do libro son correctas, e son máis interesantes ca o exemplo de XOR. Minsky e Papert non estaban interesados principalmente en se un só perceptrón podía facer XOR; interesáballes que ocorre cando aos perceptróns se lles dan campos receptivos limitados — cada unidade vendo só unha parte da entrada — e demostraron que certas propiedades globais dunha imaxe, como se unha figura está conectada, non se poden calcular dese xeito sen importar cantas unidades uses. É un resultado realmente profundo sobre a localidade, e non ten nada que ver coa historia popular.
A historia popular tamén se equivoca coa historia. Minsky e Papert falan explicitamente de perceptróns multicapa e din que a cuestión do seu poder está aberta: sospeitaban que estender a teoría sería "estéril", que é unha predición, non unha demostración, e era incorrecta. O que faltaba en 1969 non era a idea de apilar capas; era unha maneira de adestrar unha pila. A regra do perceptrón non pode facelo: precisa saber como de equivocada está cada unidade, e para unha unidade enterrada no medio non hai ningunha etiqueta coa que compararse. Esa fenda quedou aberta ata que backpropagation se popularizou en 1986,3 e pechala é o que fai o Capítulo 5.
Así que o resumo honesto é este. O libro demostrou unha limitación real dun modelo real. O colapso do financiamento do campo nos anos setenta tivo moitas causas, unha das cales foi que as promesas feitas para os perceptróns a comezos dos sesenta foran extravagantes. E o obstáculo técnico era resoluble, pero ninguén tiña aínda a ferramenta.
O que sobreviviu
Ligazón á sección: O que sobreviviuO perceptrón ten sesenta e oito anos e ti acabas de escribir un. Paga a pena ser preciso sobre que partes del seguen na máquina coa que rematarás este curso, porque a resposta é: máis das que imaxinarías.
Segue aquí. A forma — multiplicar por pesos, sumar, engadir un sesgo, aplicar unha función non lineal ao resultado — é exactamente a forma dunha unidade en todas as redes neuronais deste curso, incluídas as que hai dentro dun bloque transformer no Capítulo 9. A regra de actualizar cando hai erro é stochastic gradient descent disfrazado: é precisamente o que obtés ao aplicar o método do Capítulo 3 a unha función de perda concreta. Adestrar incrementalmente — uns poucos exemplos de cada vez en vez de todo o conxunto de datos á vez — segue sendo como se adestran hoxe os modelos a calquera escala. O Capítulo 3 mide onde cae realmente ese compromiso.
Desapareceu. O limiar en si: substituído no Capítulo 4 por unha función que emite unha probabilidade en vez dun veredicto, porque "rexeitar" e "rexeitar, pero estivo preto" son pezas de información distintas e o signo tira a diferenza ao lixo. A capa única, substituída no Capítulo 5. E as características escollidas á man: alguén escolleu anchura e peso para esta cinta, e esa elección fixo máis traballo ca o algoritmo. O Capítulo 8 é onde o modelo comeza a escoller as súas propias.
Cara a onde imos agora
Ligazón á sección: Cara a onde imos agoraO perceptrón quedou atascado en dúas cousas á vez, e resultan ser a mesma cousa.
Non pode representar XOR, porque unha liña non abonda. Arranxalo significa apilar capas: unha primeira capa que dobra o espazo, unha segunda que debuxa a liña no espazo dobrado. Iso é o Capítulo 5.
Pero non podes adestrar unha pila coa regra do perceptrón, porque só sabe "mal", e unha unidade no medio dunha rede non ten unha etiqueta propia sobre a que equivocarse. Para adestrar unha pila precisas saber como de mal, e en que dirección, para cada peso: precisas unha pendente. E a función de erro do perceptrón, a escaleira, non ten ningunha.
Así que antes da pila ten que haber unha función de perda cunha derivada útil. E tampouco unha escollida porque sexa cómoda de diferenciar: unha que veña dalgún sitio, que diga algo verdadeiro sobre os datos, e cuxo gradiente saia dese significado en vez de ser deseñado ao revés para parecer limpo.
Iso é o Capítulo 2, e comeza facendo unha pregunta que o perceptrón nunca tivo que responder: non "esta peza é boa?", senón "que probables son estas lecturas, se esta é a verdade?"
Fontes e método
Ligazón á sección: Fontes e métodoTamén paga a pena ler xunto con este capítulo: o artigo orixinal de Rosenblatt, The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain (Psychological Review 65(6), 1958), que é máis lexible do que suxire a súa reputación; McCulloch e Pitts, A Logical Calculus of the Ideas Immanent in Nervous Activity (Bulletin of Mathematical Biophysics 5, 1943), o artigo que modelou por primeira vez unha neurona como un limiar sobre unha suma ponderada; a sección sobre o perceptrón de A Course in Machine Learning, de Hal Daumé III, que deriva a mesma actualización cun énfase distinto; e os capítulos 2 e 3 de Mathematics for Machine Learning, de Deisenroth, Faisal e Ong, para a álxebra lineal, se a caixa anterior che deixou con ganas de máis do que daba.
Referencias
Ligazón á sección: Referencias-
Novikoff, A. B. J. On convergence proofs for perceptrons. Proceedings of the Symposium on the Mathematical Theory of Automata, vol. 12, pp. 615–622 (Polytechnic Institute of Brooklyn, 1962). A formulación e a demostración orixinais do límite de erros usado arriba. ↩
-
Minsky, M. and Papert, S. Perceptrons: An Introduction to Computational Geometry (MIT Press, 1969; edición ampliada de 1988). O resultado de XOR é elemental; os resultados substanciais tratan de predicados con orde limitada e conectividade. ↩
-
Rumelhart, D. E., Hinton, G. E. and Williams, R. J. Learning representations by back-propagating errors. Nature 323, pp. 533–536 (1986). ↩