Comment transformer des entrées et extraire des sorties utiles dans un réseau neuronal?

9

J'ai donc essayé de comprendre les réseaux de neurones depuis que je suis tombé sur le blog d' Adam Geitgey sur l'apprentissage automatique. J'ai lu autant que possible sur le sujet (que je peux comprendre) et je crois comprendre tous les concepts généraux et certains des fonctionnements (en dépit d'être très faible en mathématiques), les neurones, les synapses, les poids, les fonctions de coût, la rétropropagation etc. Cependant, je n'ai pas pu comprendre comment traduire des problèmes du monde réel en une solution de réseau neuronal.

Par exemple, Adam Geitgey donne comme exemple d'utilisation, un système de prédiction du prix de la maison où, étant donné un ensemble de données contenant le nombre de chambres , m² pieds , Quartier et Prix ​​de vente vous pouvez former un réseau de neurones pour pouvoir prédire le prix d'une maison. Cependant, il s'arrête avant d'implémenter une solution possible dans le code. Le plus proche qu'il obtient, à titre d'exemple, est une fonction de base montrant comment vous implémentez des pondérations:

def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
  price = 0

  # a little pinch of this
  price += num_of_bedrooms * 1.0

  # and a big pinch of that
  price += sqft * 1.0

  # maybe a handful of this
  price += neighborhood * 1.0

  # and finally, just a little extra salt for good measure
  price += 1.0

  return price 

D'autres ressources semblent se concentrer davantage sur les mathématiques et le seul exemple de code de base que je pourrais trouver que je comprends (c'est-à-dire que ce n'est pas tout le chant, toute la base de code de classification des images dansantes) est une implémentation qui forme un réseau neuronal à être un XOR porte qui ne traite que dans 1 et 0.

Il y a donc une lacune dans mes connaissances que je n'arrive pas à combler. Si nous revenons au problème de prédiction du prix des logements , comment rendre les données adaptées à l'alimentation d'un réseau neuronal? Par exemple:

  • Nbre de chambres: 3
  • Sq. pieds: 2000
  • Quartier: Normaltown
  • Prix ​​de vente: 250 000 $

Pouvez-vous simplement alimenter 3 et 2000 directement dans le réseau neuronal car ce sont des nombres? Ou avez-vous besoin de les transformer en autre chose? De même, qu'en est-il de la valeur Normaltown , qui est une chaîne, comment procédez-vous pour la traduire en une valeur qu'un réseau de neurones peut comprendre? Pouvez-vous simplement choisir un nombre, comme un index, tant qu'il est cohérent dans toutes les données?

La plupart des exemples de réseaux de neurones dont j'ai vu les nombres passer entre les couches sont de 0 à 1 ou de -1 à 1. Donc, à la fin du traitement, comment transformez-vous la valeur de sortie en quelque chose utilisable comme 185 000 $ ?

Je sais que l'exemple de prédiction du prix des maisons n'est probablement pas un problème particulièrement utile étant donné qu'il a été massivement simplifié à trois points de données. Mais je pense simplement que si je pouvais surmonter cet obstacle et écrire une application extrêmement basique qui s'entraîne à l'aide de données pseudo-réelles et crache une réponse pseudo-réelle, j'en aurai brisé le dos et pourrai lancer et approfondissez votre apprentissage automatique.

David
la source

Réponses:

10

C'est une bonne question que j'ai lutté avec moi-même lors de la première tentative de codage d'un ANN.

Vous trouverez ci-dessous une bonne solution à usage général, et c'est celle que j'ai implémentée dans mon code pour essayer de prédire des données numériques bien comportées. Si vos données ne se comportent pas bien (c.-à-d. Pleines de valeurs aberrantes), vous devrez peut-être faire plus de travail pour normaliser les entrées et les sorties. Certaines des méthodes les plus avancées sont décrites ici .

Remarque: je suppose que vous utilisez f (x) = tanh (x) comme fonction d'activation. Si vous ne l'êtes pas, vous devriez toujours pouvoir raisonner sur la façon de normaliser vos données après avoir lu ceci.

Comment préparer les données d'entrée:

L'idée de base est que vous voulez qu'une variation significative de chaque paramètre d'entrée soit reflétée par une variation significative de l'activation du neurone dans lequel ces entrées sont introduites. En regardant un tracé de la dérivée de la fonction d'activation tanh (x), vous verrez que la région de pente significative est à une distance d'un ou deux de l'origine. Cela signifie que si l'entrée de la fonction d'activation est 2000 ou 3000 (valeurs de x pour lesquelles la dérivée est négligeable), la sortie de l'activation sera presque identique ... donc l'état de votre neurone sera indépendant de la différence entre 2000 et 3000, et votre réseau ne produira jamais de puissance prédictive à partir des valeurs de cette plage.

Donc, si vous voulez entrer la superficie en pieds carrés de la maison dans un neurone, vous devez normaliser la superficie en pieds carrés afin que le réseau puisse faire la différence entre 2000 et 3000. Une façon de le faire afin que toutes les variations importantes de votre les données sont «remarquées» par le neurone pour normaliser le z-score des entrées .

  • Rassemblez toutes vos valeurs en pieds carrés (à partir de votre ensemble d'entraînement) et calculez la moyenne et l'écart-type. Stockez la moyenne et l'écart type --- vous aurez besoin de ces informations pour normaliser les nouvelles valeurs en pieds carrés lors des tests.

  • Normalisez le vecteur des valeurs en pieds carrés en soustrayant la moyenne puis en divisant le résultat par l'écart type (toutes les opérations par élément bien sûr). La soustraction de la moyenne centre vos données à l'origine et la division par l'écart-type garantit que la plupart d'entre elles se situent entre -1 et 1, où la sortie du neurone est la plus sensible à son entrée. C'est ce qu'on appelle la normalisation du score z car chaque valeur d'entrée est remplacée par son score z .

  • Faites ce qui précède pour chaque variable d'entrée.

Maintenant, lorsque vous mettez chaque valeur d'entrée dans un neurone, la sortie du neurone est une activation entre -1 et 1 (regardez l'image de tanh (x)). Étant donné que cela se trouve déjà dans la plage `` sensible '' de la fonction d'activation, vous n'avez pas à vous soucier de modifier la sortie des neurones de la couche d'entrée avant de les envoyer à la première couche cachée. Donnez simplement à tous les neurones de couche cachés les sorties de la couche précédente directement - ils seront en mesure de les gérer très bien.

Lorsque vous atteignez la dernière couche (le ou les neurones de sortie), vous obtenez à nouveau une autre activation entre -1 et 1. Vous devez reconvertir cela en une valeur pour la maison en question , si cette valeur sera utilisée comme une prédiction dans un ensemble de tests ou pour calculer une erreur pendant l'entraînement. Quelle que soit la façon dont vous procédez, il vous suffit d'être cohérent et d'utiliser la même procédure de dénormalisation lors de la formation et des tests. Une façon d'y penser est la suivante: lorsque le ou les neurones de sortie renvoient 1, cela signifie que le réseau renvoie la valeur maximale possible de la maison comme prédiction. Quelle devrait être la valeur la plus élevée que le réseau puisse estimer? La bonne approche ici dépend simplement de votre application. C'est ce que j'ai fait:

  • Calculez la moyenne de [la / chaque] variable de sortie et enregistrez-la.
  • Calculez l'écart maximal de la variable de sortie par rapport à la moyenne. Python:MaxDev = max([abs(DataPoint-numpy.mean(TrainingData)) for DataPoint in TrainingData])
  • Lorsque le réseau renvoie des sorties entre -1 et 1, multipliez la sortie par MaxDevet ajoutez-la à la moyenne.

Deux vérifications rapides de base que vous pouvez faire pour voir si votre schéma de normalisation-renormalisation est approprié (ce sont des conditions nécessaires, mais peut-être pas suffisantes):

  1. Si toutes les valeurs d'entrée sont moyennes (par exemple, nombre moyen de chambres, pieds carrés moyens, etc.), la sortie du réseau est-elle également égale à la moyenne de la variable de sortie (par exemple, la valeur de la maison)? (Ça devrait être.)
  2. Si toutes les valeurs d'entrée sont anormalement hautes / basses, la sortie du réseau est-elle également anormalement haute / basse? (Cela ne fonctionne que si toutes les entrées sont liées positivement à la sortie ... si certaines d'entre elles sont liées de manière inversée, vous devrez réfléchir un peu plus).

Observez que le schéma présenté ici remplit ces deux conditions.

Notez que ce schéma permettrait à votre réseau de prédire uniquement les valeurs de maison dans la plage de valeurs de maison dans votre ensemble de données de formation. Selon l'application, ce comportement peut être souhaitable ou indésirable.

Par exemple: vous souhaiterez peut-être empêcher votre réseau de prévoir des valeurs de maison négatives. Réfléchissez à la façon dont vous procéderiez. Dénormaliser la sortie afin que -1 soit mappé à 0.

Si vous ne souhaitez définir aucune limite sur les valeurs que votre réseau peut prédire, vous pouvez exécuter la sortie du réseau via une fonction qui mappe la plage [-1,1] à tous les nombres réels ... comme arctanh (x)! Tant que vous le faites pendant la formation, votre réseau ajustera ses pondérations pour s'adapter à cela.

J'espère que cela a été utile. Faites-moi savoir si vous avez d'autres questions. Mon module ANN est en Python, soit dit en passant, donc je pourrais avoir des conseils spécifiques à la langue.

Marko Bakić
la source
C'était très utile! Chaque blog / tutoriel que je rencontre semble éviter (presque délibérément) de décrire ce processus, mais oui, tout est logique. Il faudra un certain temps pour que je digère correctement, mais je reviendrai si j'ai des questions de suivi. Infiniment reconnaissant!
David
Donc, quelques questions. Si mon carré. Les données d'entraînement des pieds étaient {2000, 800, 850, 550, 2000}, alors mes entrées de score z pour {1900, 1500, 600} seraient (si j'ai calculé correctement) {1,0496, 0,4134, -1,0177}. Donc, l'une de ces valeurs est> 1 et l'autre est <-1, que ferais-je avec celles-ci? Entrez-les dans les nœuds de la couche d'entrée indépendamment ou arrondissez-les à 1 et -1? Pourquoi 1900 et 600 produisent-ils ces valeurs alors qu'elles se situent dans la plage 550-2000? Est-ce juste une ruse des données car il y a un si petit ensemble de données?
David
0unenthemuneXjemum
N'oubliez pas que les entrées n'ont pas besoin d'être strictement comprises entre 1 et -1. Tout ce dont vous avez besoin pour les entrées est que la plupart des données se trouvent dans cette plage. Une valeur supérieure ou inférieure à un signifie que le point est à plus d'un écart-type de la moyenne, de sorte que ce point est plus proche de l'extrémité supérieure des données. Il devrait être un peu rare que vos données sortent de [-1, 1], encore plus rare qu'elles sortent de [-2, 2] et extrêmement rares de sortir de [-3, 3]. Regardez tanh (x) et vous verrez que la plage sensible n'est pas strictement entre -1 et 1, mais va un peu plus loin que cela.
Marko Bakić, le
En ce qui concerne la dénormalisation de sortie, cette dénormalisation min-max est ce que j'ai fait dans mon implémentation, et votre interprétation est correcte, mais vous n'avez pas nécessairement à le faire. Vous pouvez faire en sorte que 1 correspond à deux fois la valeur maximale de la maison - de cette façon, votre réseau serait en mesure de prédire les valeurs de la maison au-dessus de ce sur quoi vous l'avez formé.
Marko Bakić