SARAH gagne quelques Neurones (2/2)
Cet article fait suite à l’article précédent SARAH gagne quelques Neurones (1/2)
Eedomus 2.0
Pour interroger le capteur de luminosité j’ai mis à jour le plugin Eedomus en v2.0. Il est maintenant possible de lire ou modifier des périphériques de la box.
[crayon]
exports.action = function(data, callback, config, SARAH){
SARAH.call(‘eedomus’, { ‘periphId’ : LUMENS}, function(options){
var lumens = options.json.last_value;
…
scenario(state, callback, SARAH);
});
}
[/crayon]
La méthode SARAH.call
est une version simplifiée de SARAH.run
qui sera disponible en v2.9
Algorithmique
Le plugin scenario
peut prendre 2 états: 1
Allumer et 0
Éteindre les lampes de la pièce.
[crayon]
var scenario= function(state, callback, SARAH){
var tts = »;
if (state == 1){
lights(BUREAU, true, SARAH);
lights(SALON, true, SARAH);
tts = ‘Bonjour’;
}
else {
lights(BUREAU, false, SARAH);
lights(SALON, false, SARAH);
tts = ‘Aurevoir’;
}
callback({‘tts’: tts});
}
[/crayon]
Learn
Le plugin scenario
peut être appelé avec un paramètre learn
pour apprendre le comportement.
- Calendrier:
learn=false
- Mouvement:
learn=false
- Reconnaissance vocale:
learn=true
- QR Code:
learn=true
Subtilités
1. Les ordres d’éteindre sont toujours exécutés indépendamment de la luminosité:
- Je vais me coucher: c’est explicite on va pas négocier
- Je ne suis pas là: il faut faire des économies d’énergie
2. Le temps est très important ! On peut éteindre ou allumer pour des raisons de luminosité mais aussi d’heure de la journée.
[crayon]
set.push({‘input’: {l: lum/100, t: minutes() }, ‘output’: {s: state}});
[/crayon]
Typiquement je vais me coucher, j’éteint explicitement, le réseau apprends mais ce n’est pas lié à la luminosité.
Code
Le code s’initialise avec un set
de valeurs prédéterminées.
[crayon]
var brain = require(‘./lib/brain’);
var set = [{‘input’: {l: 100/100, t: 0}, ‘output’: {s: 0}},
{‘input’: {l: 0/100, t: 0}, ‘output’: {s: 1}}];
var net = new brain.NeuralNetwork();
net.train(set);
[/crayon]
La fonction compute()
se charge d’améliorer le set
et relancer l’apprentissage.
La librairie brain.js
impose de refaire tout l’apprentissage. Cela pourrait poser des problèmes de perfs à terme.
[crayon]
var compute = function(learn, state, lum){
if (learn){
set.push({‘input’: {l: lum/100, t: minutes() }, ‘output’: {s: state}});
net.train(set);
return state;
}
// Guess only for switch ‘on’. Not ‘off’
if (state == 1){
return Math.round(net.run({l: lum/100, t: minutes() }).s);
}
return state;
}
[/crayon]
La fonction minutes()
retourne le nombre de minutes écoulées dans la journée.
Sauvegarde du réseau
Au moment de l’apprentissage il faut enregistrer l’ensemble des données:
[crayon]
if (learn){
fs.writeFileSync(file, JSON.stringify(set), ‘utf8′);
}
[/crayon]
Au chargement du plugin il faut relire le réseau:
[crayon]
if (fs.existsSync(file)){
set = JSON.parse(fs.readFileSync(file,’utf8’));
}
net.train(set);
[/crayon]
Conclusion
Lors d’un mouvement, l’algo détermine en fonction de l’heure et de la luminosité si il faut vraiment allumer les lampes.
Action | Apprendre ? | Raisonner ? |
---|---|---|
Mouvement | Non | Oui |
Plus de Mvt | Non | Non |
Vocale On | Oui | Non |
Vocale Off | Oui | Non |
Si SARAH allume alors que ce n’est pas nécessaire. Pour lui apprendre je dois éteindre explicitement.
Mais comme le remarque Giom, SARAH va apprendre qu’il faut éteindre pour (Luminosité + Lampe) alors qu’elle devrait apprendre de ne pas allumer pour (Luminosité)
Il faudra peut-être mémoriser l’état N-1 pendant X minutes. Le code est ici: http://jsfiddle.net/jpencausse/Ukj3t/