IA: apprentissage d'un neurone
RésoluPhil_1857 Messages postés 1872 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
M'intéressant à l'IA, j'ai conçu ce code pour apprendre à un neurone à 7 entrées à sortir 1 si les 7 entrées sont égales à 1, et 0 pour 8 autres cas.
- Les cas sont dans la liste nommée inputs.
- Le neurone est donc censé sortir 1 pour inputs[8]
- Ma variable total accumule les 9 sorties possibles pour les 9 inputs.
On sort de la boucle lorsque total arrive à cette valeur : '0000000010'
Le problème est que la boucle tourne indéfiniment
A noter que ceci fonctionne pour tous les autres cas, par exemple en testant avec inputs[0], on arrive bien
à ça : '1000000000', et on sort de la boucle
J'ai cherché, évidemment, mais si un œil neuf pouvait se poser sur le problème ...
import os def get_output(input_nb): ''' checks if neuron fires on "input_nb" ''' e_sum = 0 for k in range(len(weights)): e_sum += inputs[input_nb][k]*weights[k] return(1 if e_sum > 0 else 0) def learning_phase(input_nb): ''' Learning phase : calculates the output of the neuron and updates the weights ''' output = get_output(input_nb) expected_output = 0 if(input_nb == 8): expected_output = 1 delta = expected_output - output for k in range(len(weights)): weights[k] += (inputs[input_nb][k] * delta * 10) inputs = [[1,1,1,1,1,0,1],[0,0,1,1,0,0,0],[1,0,1,0,1,1,1],[0,0,1,1,1,1,1],[0,1,0,1,0,1,0],[0,1,0,1,1,1,1],[1,1,0,1,1,1,1], [0,0,1,1,0,0,1],[1,1,1,1,1,1,1],[0,1,1,1,1,1,1]] weights = [0,0,0,0,0,0,0] while(True): os.system('cls') print('\nApprentissage ...') total = '' for input_nb in range (len(inputs)): learning_phase(input_nb) for input_nb in range (len(inputs)): total += str(get_output(input_nb)) if(total == '0000000010'): break print(total) print('Apprentissage terminé : {}'.format(total)) input('Entrée ...')
Windows / Edge 109.0.1518.78
- IA: apprentissage d'un neurone
- Whatsapp opposition ia - Guide
- Ia whatsapp - Guide
- Comment utiliser l'ia - Accueil - Guide Intelligence artificielle
- My ia - Accueil - Intelligence artificielle
- Emo ia - Accueil - Intelligence artificielle
11 réponses
Bonsoir.
Je n'ai pas bien saisi la logique de ton code, mais tout ce que je peux constater est qu'il entre dans un cycle infini entre 0010101010 et 1010111010.
Testé simplement en enregistrant dans un fichier les valeurs.
f = open('result', 'w') i = 0 while True: # os.system('cls') # print('\nApprentissage ...') total = '' for input_nb in range(len(inputs)): learning_phase(input_nb) for input_nb in range(len(inputs)): total += str(get_output(input_nb)) f.write(total + '\n') if total == '0000000010' or i == 1000: f.close() break # print(total) i += 1
Pourquoi, aucune idée ^^
Ce ne serait pas mieux de travailler avec du binaire ?
bonjour,
Tu devrais sortir de la boucle quand weights n'évolue plus, c'est à ce moment-là que l'apprentissage est terminé.
En fait, tu cherches des valeurs de w[] qui vont te donner, pour tous les i[]:
- somme(w[x]*i[x]) > 0 ssi tous les i[x] sont égaux à 1
Essaie avec deux entrées, quels sont les valeurs de w0 et de w1 qui sont des solutions de:
- w0 <= 0
- w1 <= 0
- w0 + w1 >0
Voici un bel exemple de situation où l'IA ne dispense pas d'utiliser son intelligence humaine.
Bonjour,
"Tu devrais sortir de la boucle quand weights n'évolue plus, c'est à ce moment-là que l'apprentissage est terminé."
Non, c'est terminé lorsque l'affichage final est 0000000010, c'est à dire lorsque le neurone répond 1 avec
les 7 inputs à 1, et 0 dans tous les autres cas
L'affichage sur mon image ci-dessus montre qu'il y a des 1 pour d'autres entrées, ce qui n'est pas bon
En fait, je me demande si je ne suis pas dans le cas où les différente réponses ne forment pas un modèle
linéairement séparable, et donc il n'y a pas de solution
Exemple:
si on apprend à un neurone à 2 entrées la fonction ET, que l'on trace un système d'axes pour y placer les
réponses 0 et 1, on peut tracer une ligne qui sépare les 0 des 1
par contre, si l'on essaie avec la fonction XOR, c'est impossible, l'apprentissage ne peut se faire,
pour y arriver il faut ajouter un 2eme neurone connecté au 1er
C'est amusant que tu prennes comme exemple l'opérateur ET, car c'est exactement cela que tu utilises ici sans succès.
As-tu essayé ton code avec 2 entrées? Comprends tu pourquoi il ne fonctionne pas, malgré que ce soit un modèle linéairement séparable?
Quelle est l'équation d'une droite? Quelle est l'équation que tu cherches dans ton code?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionBonjour yg_be,
et donc, tu as fait quoi, pour résumer tout ça ?
def get_output(inp): ''' checks if neuron fires on "input_nb" ''' e_sum = -weights[len(weights)-1] for k in range(len(weights)-1): e_sum += inp[k]*weights[k] return(1 if e_sum > 0 else 0) def learning_phase(input): ''' Learning phase : calculates the output of the neuron and updates the weights ''' output = get_output(input) expected_output = 1 for k in range(L): if(input[k]==0): expected_output = 0 break delta = expected_output - output weights[L] -= delta*L for k in range(L): weights[k] += delta * input[k] def bt(nb,bt): return (int(int(nb)/int((2**bt))))%2 def lst(n): return [bt(n,b) for b in range(L)] L=7 inputs=[lst(x) for x in range(2**L)] weights = [0 for i in range(L+1)] i=0 while True: i+=1 print('\nApprentissage ...',str(i)) total = '' ow=weights.copy() for input_nb in range (len(inputs)): learning_phase(inputs[input_nb]) for input_nb in range (len(inputs)): total += str(get_output(inputs[input_nb])) print(total) print(weights) if weights==ow: break print('Apprentissage terminé : {}'.format(total)) for input_nb in range (len(inputs)): print (str(get_output(inputs[input_nb])),inputs[input_nb]) input('Entrée ...')
all right, je vais examiner tout ça :-)
.........................
Holà yg_be,
La grosse différence avec mon code, c'est l'ajout d'un 8eme poids avec un calcul de sa valeur à part
puisque ensuite on boucle de 0 à 6 pour mettre à jour les 7 poids sur les 7 entrées
Et on a bien le résultat attendu !
peux-tu expliquer cela ?
aurais-tu ajouté un "biais" ?
Moi, je l'avais fait dans mon réseau à 2 neurones pour la fonction XOR:
1er neurone avec 2 entrées et un biais =1
2eme neurone avec 3 entrées (dont la valeur de sortie du neurone 1) et un biais =1
Pourquoi un "poids" de plus? Parce que la solution comporte N+1 éléments, pas N. Dans un espace à N dimensions, une "séparation linéaire", pour reprendre ton vocabulaire, est définie par N+1 valeurs, pas par N valeurs.
Pour simplifier le vocabulaire, prenons un exemple à deux entrées.
Une séparation linéaire, c'est donc une séparation faite par une droite. L'équation d'une droite, c'est ax+by=c.
Toi, comme tu avais construit ton programme, tu cherchais a et b, en supposant que c était nul. Tu te limites donc aux droites passant par l'origine, tandis que ton modèle est linéairement séparable, mais par une droite ne passant pas par l'origine.
Les deux "poids" de départ, ce sont a et b. Le "poids" de plus, c'est le troisième élément à chercher, c.
Holà yg_be,
Je dois quand même te donner la finalité de tout ceci
Voici ce que j'ai fait avec ton exemple:
# -*- coding:Latin-1 -*- # Reconnaissance des chiffres de 0 à 9 sur l'affichage à 7 leds # 10 neurones, chacun connecté aux 7 leds # _7_ # 2 | | 3 # |_6_| # 1 | | 4 # |_ _| # 5 #07/02/2023 15:44:14 import os import random import pickle def get_output(input_nb, neuron): ''' checks if neuron fires on "input_nb" ''' e_sum = -weights[neuron][L] for k in range(L): e_sum += inputs[input_nb][k]*weights[neuron][k] return(1 if e_sum > threshold else 0) def learning_phase(input_nb,n): ''' Learning phase : calculates the output of the neuron and updates the weights ''' output = get_output(input_nb,n) expected_output = 0 if(input_nb == n): expected_output = 1 delta = expected_output - output weights[n][L] -= delta*L for k in range(L): weights[n][k] += delta * inputs[input_nb][k] #Lecture des données filename = 'chiffres_0_9.txt' with open(filename, 'r') as ofi: block = ofi.read() inputs = eval(block) neurons_nb = len(inputs) threshold = 0 L=7 weights = [[0 for j in range(L+1)] for i in range(neurons_nb)] data_file = 'neurons_data.dat' #Initialise les chaines représentant les suites de sorties valides par neurone patterns = {} for k in range(neurons_nb): patterns[k] = '' for n in range(len(inputs)): if(k == n): patterns[k] += '1' else: patterns[k] += '0' #Apprentissage print('Apprentissage ...') i=0 for k in range(neurons_nb): while True: i+=1 total = '' for input_nb in range (len(inputs)): learning_phase(input_nb,k) for input_nb in range (len(inputs)): total += str(get_output(input_nb,k)) if(total == patterns[k]): print(total) break print('\nApprentissage terminé en {} pas'.format(i)) #Enregistrement des poids wl = [] for k in range(neurons_nb): wl.append(weights[k]) with open(data_file, 'wb') as fo: pickle.dump(neurons_nb, fo) pickle.dump(wl, fo) print('Création du fichier {}'.format(data_file)) input('Entrée ...')
Les 10 listes de 0 et 1 représentent l'allumage ou non de chacune des 7 leds d'un affichage de chiffres
J'ai 10 neurones, chacun flashant sur un des 10 chiffres
En fin d'apprentissage, j'enregistre les poids dans un fichier (pickle, c'est pratique)
J'ai un 2eme programme qui lit le fichier, et identifie les chiffres que l'on initialise en cliquant les segments:
C'est ce qui reste à régler, en effet si on entre, par exemple, cette série: 1,0,0,0,0,0,0 qui ne correspond à
aucun chiffre, l'un des 10 neurones flashe
Ceci dit les 10 chiffres de 0 à 9 sont bien reconnus...
Bonjour,
Pas besoin de fichier texte, on le voit à l'affichage: au bout d'un certain nb de tours on oscille sans fin
entre les 2 valeurs