IA: apprentissage d'un neurone

Résolu/Fermé
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - Modifié le 7 févr. 2023 à 15:21
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - 10 févr. 2023 à 14:29

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

A voir également:

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 ?

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
5 févr. 2023 à 09:53

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

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
4 févr. 2023 à 20:55

bonjour,

Tu devrais sortir de la boucle quand weights n'évolue plus, c'est à ce moment-là que l'apprentissage est terminé.

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
5 févr. 2023 à 09:03

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.

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
5 févr. 2023 à 10:16

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

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
5 févr. 2023 à 12:53

Pourquoi continuer l'apprentissage quand le neurone ne progresse plus?  Qu'il ait atteint ou non la bonne valeur de weights, inutile de continuer si il arrête de progresser.

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
5 févr. 2023 à 13:03

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?

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477 > yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024
5 févr. 2023 à 14:20

Après avoir adapté la formule, j'ai aussi été obligé d'ajouter des inputs, de façon à avoir assez de points pour permettre l'apprentissage.

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
6 févr. 2023 à 13:31

Bonjour yg_be,

et donc, tu as fait quoi, pour résumer tout ça ?

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
6 févr. 2023 à 16:35
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 ...')
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 6 févr. 2023 à 18:22

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

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
6 févr. 2023 à 19:18

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.

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
7 févr. 2023 à 13:58

Bonjour yg_be

je vois le truc

Merci pour tout

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
7 févr. 2023 à 15:57

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:

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
7 févr. 2023 à 16:45

As-tu testé tes neurones si on leur présente une autre combinaison que ces dix combinaisons?  Donc si on leur présente une "image" qui n'est pas un chiffre?

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 7 févr. 2023 à 17:11

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...

0
yg_be Messages postés 22747 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 2 mai 2024 1 477
7 févr. 2023 à 19:27

Je pense qu'il est nécessaire d'entrainer chaque neurone sur les 128 possibilités, pas seulement sur 10 possibilités.

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
8 févr. 2023 à 10:29

Bonjour yg_be,

oui, ce sera la prochaine étape

Pour cette fois, je ferme cet appel 

merci pour tout

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
10 févr. 2023 à 14:29

Hello Yg_be,

J'ai réglé le problème en ajoutant les 118 combinaisons aux 10 premières

0