Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Prédiction de pluie DIY utilisant Arduino, Python et Keras

Composants et fournitures

Petite boîte en plastique avec couvercles amovibles (la mienne a des vis)
× 1
trois piles AAA
× 1
trois piles rechargeables AAA
× 1
Petit panneau solaire 6V
× 1
SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
diode 1N4004
× 1
Transistor à usage général NPN
× 1
un capteur de pluie
× 1
Module de communication série HC-12
× 1
Module série USB HC-12
× 1
Déploiement du capteur atmosphérique SparkFun - BME280
× 1
BH1750
× 1
PCB, fils, soudure, connecteur à vis enfichable KF301-2P , connecteurs pcb mâle et femelle, colle
× 1
Régulateur 3.3V
× 1

Outils et machines nécessaires

Adaptateur USB vers série FTDI FT232RL
Perceuse
Fer à souder (générique)
Tournevis

À propos de ce projet

D'abord quelques mots sur ce projet, la motivation, les technologies impliquées et le produit final que nous allons construire.

Donc le gros objectif ici est évidemment de prédire la pluie à l'avenir (on essaiera 6 heures). La prédiction sera un oui ou un non (booléen en termes de programmation). J'ai recherché des tutoriels sur ce sujet et je n'en ai pas trouvé un qui soit complet à tous points de vue. Donc, le mien adoptera une toute nouvelle approche et en abordera tous les aspects. Pour cela nous allons :

  • construire la station météo nous-mêmes. La station doit être complètement hors réseau avec un panneau solaire, et un mode d'alimentation extrêmement faible (quelques dizaines de microampères heure)
  • programme la station pour qu'elle collecte des données et les transmet toutes les dix minutes à une station de base
  • collecter les données sur la station de base et les stocker (dans une base de données)
  • à l'aide de réseaux de neurones (bibliothèque Keras) et d'autres bibliothèques Python comme les pandas filtrent, nettoient et prétraitent les données, puis les transmettent à un réseau de neurones pour former un "modèle" permettant de prédire qu'il pleuvra ou non
  • enfin prédire s'il va pleuvoir ou non au cours des 6 prochaines heures et notifier les utilisateurs par e-mail

J'ai personnellement utilisé cette station météo pour collecter des données (vous pouvez télécharger les données dans les prochaines étapes si vous le souhaitez). Avec seulement environ 600 jours de données météorologiques, le système peut prédire s'il pleuvra ou non dans les 6 prochaines heures avec une précision d'environ 80% en fonction des paramètres, ce qui n'est pas si mal.

Ce tutoriel vous guidera à travers toutes les étapes nécessaires pour prévoir les précipitations à partir de zéro. Nous allons créer un produit final qui fait un travail pratique, sans utiliser d'API météo ou d'apprentissage automatique externes. Nous apprendrons en cours de route comment construire une station météorologique pratique (faible puissance et hors réseau) qui collecte réellement des données sur de longues périodes sans entretien. Après cela, vous apprendrez à le programmer à l'aide d'Arduino IDE. Comment collecter des données dans une base de données sur une station de base (serveur). Et comment traiter les données (Pandas) et appliquer des réseaux de neurones (Keras) puis prédire les précipitations.

Étape 1 : pièces et outils pour la construction de la station

Pièces :

1. Petite boîte en plastique avec couvercles amovibles (la mienne a des vis). La taille de la boîte doit être suffisamment grande pour contenir les petits composants et les batteries. Ma boîte a 11 x 7 x 5 cm

2. trois porte-piles AAA

3. trois piles rechargeables AAA

4. Petit panneau solaire 6V

5. Arduino Pro Mini 328p

6. une diode, 1N4004 (pour empêcher le courant inverse des batteries au panneau)

7. un petit transistor NPN et une résistance 1k (pour allumer et éteindre les composants)

8. un capteur de pluie

9. Module de communication série HC-12

10. Module série USB HC-12 (pour la station de base)

11. Module capteur bosch BME280 (pour humidité, température, pression)

12. Module de détection de lumière BH1750

13. PCB, fils, soudure, connecteur à vis enfichable KF301-2P, connecteurs pcb mâle et femelle, colle

14. Régulateur 3,3V

15. une station de base :un PC ou une carte de développement fonctionnant en permanence. Son rôle est de collecter des données, d'entraîner le modèle de prévision de pluie et de faire des prévisions

Outils :

1. Adaptateur USB vers série FTDI FT232RL pour programmer l'Arduino Pro Mini

2. IDE Arduino

3. Percer

4. Scie à lame fine

5. Tournevis

6. Fer à souder

7. Coupe-fil

Compétences :

1. Souder, consultez ce tutoriel

2. Programmation arduino de base

3. Configuration du service Linux, installation du package

4. Quelques compétences en programmation

Étape 2 : Construire la station météo

La station météo est composée des ensembles de composants suivants :

1. la boite avec le panneau solaire collé dessus

2 . le PCB avec l'électronique à l'intérieur

3. le support de batterie aussi à l'intérieur

4. le BME280 et les capteurs de lumière et de pluie à l'extérieur

1. La boîte a besoin de 4 trous, un pour les fils du panneau solaire, trois autres pour les capteurs qui seront placés à l'extérieur. Percez d'abord les trous, ils doivent être suffisamment gros pour que les fils mâle-femelle dépassent et aillent aux capteurs. Une fois les trous percés, collez le panneau sur un côté de la boîte et faites passer ses fils à travers un trou à l'intérieur

2. Le PCB contiendra l'arduino, le HC-12, le régulateur 3.3V, la diode, le transistor, la résistance et deux KF301-2P

  • soudez d'abord les deux connecteurs PCB femelles sur le PCB de l'arduino, soudez les connecteurs PCB mâles à l'arduino et placez l'arduino sur le PCB
  • la led arduino doit être retirée ou au moins une de ses broches. c'est très important parce que la led va puiser une grande quantité d'énergie. Veillez à ne pas endommager d'autres composants
  • souder le transistor, la résistance et le régulateur 3,3 V
  • souder les deux KF301-2P. L'un sera pour le panneau solaire, l'autre pour le support de batterie
  • souder trois connecteurs PCB femelles :pour le capteur de lumière, le BME280 et le capteur de pluie
  • souder de petits fils pour connecter tous les composants PCB (vérifier les images et le schéma fritzing)

3. placez 3 piles AAA NiMH chargées à l'intérieur du support et placez-le à l'intérieur de la boîte, en connectant les fils au connecteur KF301-2P

4. connecter le BME280 et les capteurs de lumière de l'extérieur du boîtier à leurs connecteurs mâles correspondants

Pour le capteur de pluie, soudez-y trois fils (Gnd, Vcc, signal) et de l'autre côté soudez les broches mâles qui iront à l'intérieur de la boîte à ses connecteurs mâles correspondants

La dernière chose serait de placer la station dans sa position finale. J'ai choisi une position à l'abri de la pluie et de la neige. J'ai choisi des fils plus longs pour le capteur de pluie et je l'ai placé séparément sous la pluie sur un support stable. Pour la boîte principale, j'ai choisi un type spécial de ruban adhésif (vérifiez les photos) mais tout ce qui tient la boîte fera l'affaire.

croquis.fzz

Étape 3 : Code Arduino

Dans cette étape, vous apprendrez quelles bibliothèques externes sont nécessaires, nous présenterons le code et son fonctionnement et, bien sûr, vous pourrez le télécharger ou le copier-coller dans Arduino IDE et le télécharger sur la station météo.

Le rôle de la station météo est de transmettre à une station de base toutes les 10 minutes des données sur ses capteurs.

Commençons par décrire ce que fait le programme de la station météo :

1. lire les données des capteurs (humidité, température, pression, pluie, lumière, tension)

2. transmet les données codées via une deuxième ligne série logicielle.

Les données encodées ressemblent à ceci :

H1:78|T1:12|PS1:1022|L1:500|R1:0|V1:4010|

La déclaration ci-dessus signifie que :l'humidité de la station "1" est de 78 %, la température de la station 1 est de 12 degrés, la pression est de 1022 bars, le niveau de luminosité de 500 lux, la pluie de 0 et la tension de 4010 millivolts

3. mettre hors tension les composants auxiliaires :capteurs et dispositif de communication

4. met l'arduino en mode veille pendant 10 minutes (cela le fera consommer moins de 50 microampères)

5. allumez les composants et répétez les étapes 1 à 4

Un petit ajustement supplémentaire ici, si le niveau de tension est supérieur à 4,2 V, l'arduino utilisera la fonction de veille normale "retard (millisecondes)". Cela augmentera considérablement la consommation d'énergie et diminuera rapidement la tension. Cela empêche efficacement le panneau solaire de surcharger les batteries.

Vous pouvez obtenir le code de mon dépôt Github ici :https://github.com/danionescu0/home-automation/tre...

Ou en le copiant-collant par le bas, de toute façon supprimez simplement la ligne avec "transmitSenzorData("V", capteurs.voltage);"

#include "LowPower.h"
#include "SoftwareSerial.h"#include "Wire.h"#include "Adafruit_Sensor.h"#include "Adafruit_BME280.h"#include "BH1750.h "SoftwareSerial serialComm(4, 5); // RX, TXAdafruit_BME280 bme; BH1750 lightMeter;const byte rainPin =A0;byte sensorCode =1;/** * niveau de tension qui mettra le microcontrôleur en veille profonde au lieu d'un sommeil normal */int voltageDeepSleepThreshold =4200 ; const byte peripherialsPowerPin =6;char buffer[] ={' ',' ',' ',' ',' ',' ',' '};struct sensorData { octet humidité; température intérieure; pluie d'octets; pression int; longue tension; lumière int; };sensorData capteurs;void setup() { Serial.begin(9600); serialComm.begin(9600); pinMode(périphériquesPowerPin, OUTPUT); digitalWrite(périphériquesPowerPin, HIGH); retard (500); if (!bme.begin()) { Serial.println("Impossible de trouver un capteur BME280 valide, vérifiez le câblage!"); while (1) { customSleep(100); } } Serial.println("Initialisation terminée avec succès"); retard (50); digitalWrite(peripherialsPowerPin, HIGH);}boucle vide() { updateSenzors(); transmettreDonnées(); customSleep(75); }void updateSenzors() { bme.begin(); lightMeter.begin(); retard (300); capteurs.temperature =bme.readTemperature(); capteurs.pression =bme.readPressure() / 100.0F; capteurs.humidité =bme.readHumidity(); sensor.light =lightMeter.readLightLevel(); capteurs.tension =readVcc(); capteurs.rain =readRain();}void transmitData(){ emptyIncommingSerialBuffer(); Serial.print("Temp:");Serial.println(sensors.temperature); Serial.print("Humid:");Serial.println(capteurs.humidité); Serial.print("Pressure:");Serial.println(capteurs.pression); Serial.print("Light:");Serial.println(sensors.light); Serial.print("Tension :");Serial.println(sensors.voltage); Serial.print("Rain:");Serial.println(sensors.rain); transmitSenzorData("T", capteurs.temperature); transmitSenzorData("H", capteurs.humidité); transmitSenzorData("PS", capteurs.pression); transmitSenzorData("L", sensor.light); transmitSenzorData("V", capteurs.tension); transmitSenzorData("R", sensor.rain);}void emptyIncommingSerialBuffer(){ while (serialComm.available()> 0) { serialComm.read(); retard (5) ; }}void transmitSenzorData(Type de chaîne, valeur int){ serialComm.print(type); serialComm.print(sensorsCode); serialComm.print(":"); serialComm.print(valeur); serialComm.print("|"); delay(50);}void customSleep(long EightSecondCycles){ if (sensors.voltage> voltageDeepSleepThreshold) { delay(huitSecondCycles * 8000); retourner; } digitalWrite(peripherialsPowerPin, LOW); for (int i =0; i

Avant de télécharger le code, téléchargez et installez les bibliothèques arduino suivantes :

* Bibliothèque BH1750 :https://github.com/claws/BH1750 * Bibliothèque LowPower :https://github.com/rocketscream/Low-Power

* Bibliothèque de capteurs Adafruit :https://github.com/adafruit/Adafruit_Sensor

* Bibliothèque Adafruit BME280 :https://github.com/adafruit/Adafruit_Sensor

Si vous ne savez pas comment faire, consultez ce tutoriel.

Étape 4 :Préparation de la station de base

La station de base se composera d'un ordinateur Linux (ordinateur de bureau, ordinateur portable ou carte de développement) avec le HC-12 USB module attaché. L'ordinateur doit rester allumé en permanence pour collecter des données toutes les 10 minutes depuis la station.

J'ai utilisé mon ordinateur portable avec Ubuntu 18.

Les étapes d'installation :

1. Installez anaconda. Anaconda est un gestionnaire de packages Python et cela nous permettra de travailler facilement avec les mêmes dépendances. Nous pourrons contrôler la version Python, et chaque version du package

Si vous ne savez pas comment l'installer, consultez ce tutoriel :https://www.digitalocean.com/community/tutorials/h... et suivez les étapes 1 à 8

2. Installez mongoDb. MongoDb sera notre base de données principale pour ce projet. Il stockera des données sur toutes les séries temporelles des capteurs. Il est sans schéma et pour notre objectif, il est facile à utiliser.

Pour connaître les étapes d'installation, consultez leur page :https://docs.mongodb.com/v3.4/tutorial/install-mon...

J'ai utilisé une ancienne version de mongoDb 3.4.6, si vous suivez le tutoriel ci-dessus, vous obtiendrez exactement cela. En principe, il devrait fonctionner avec la dernière version.

[Facultativement] ajoutez un index sur le champ de date :

météo des mangoustes db.weather_station.createIndex({"date" :1}) 

3. Téléchargez le projet à partir d'ici :https://github.com/danionescu0/home-automation. Nous utiliserons le dossier weather-predict

sudo apt-get install gitgit clone https://github.com/danionescu0/home-automation.gi... 

4. Créer et configurer l'environnement anaconda :

cd weather-predict # crée un environnement anaconda nommé "weather" avec python 3.6.2conda create --name weather python=3.6.2 # activate environmentconda activate weather# install all packages pip install -r requirements.txt  

Cela créera un nouvel environnement anaconda et installera les packages nécessaires. Certains des packages sont :

Keras (couche de réseau neuronal de haut niveau, avec cette bibliothèque, nous ferons toutes nos prédictions de réseau neuronal)

pandas (outil utile qui manipule les données, nous l'utiliserons beaucoup)

pymongo (pilote python mongoDb)

sklearn (outils d'exploration et d'analyse de données)

Configurer le projet

Le fichier de configuration est situé dans le dossier weather-predict et se nomme config.py

1. si vous installez MongoDb à distance ou sur un autre port changez le "host" ou le "port" dans le

mongodb ={ 'hôte':'localhost', 'port':27017}... 

2. Nous devons maintenant connecter l'adaptateur série USB HC-12. Avant de courir :

ls -l /dev/tty* 

et vous devriez obtenir une liste des périphériques montés.

Insérez maintenant le HC-12 dans un port USB et exécutez à nouveau la même commande. Cela devrait être une nouvelle entrée dans cette liste, notre adaptateur série. Modifiez maintenant le port de l'adaptateur dans la config si nécessaire

serial ={ 'port':'/dev/ttyUSB0', 'baud_rate':9600} 

Les autres entrées de configuration sont des chemins de fichiers par défaut, aucun changement n'est nécessaire.

Étape 5 :Utilisez la station météo en pratique

Ici, nous allons discuter des choses de base sur l'importation de mes données de test, l'exécution de tests dessus, la configuration de vos propres données, l'affichage de graphiques et la configuration d'un e-mail avec prédiction pour les prochaines heures.

Si vous souhaitez en savoir plus sur son fonctionnement, consultez l'étape suivante « Comment ça marche ? »

Importer mes données déjà collectées

MongoDb est livré avec une commande cli pour importer des données depuis json :

mongoimport -d weather -c weather_station --file sample_data/weather_station.json 

Cela importera le fichier à partir des exemples de données dans la base de données « météo » et la collection « points de données »

Un avertissement ici, si vous utilisez mes données recueillies et que vous les combinez avec vos nouvelles données locales, la précision peut baisser en raison des petites différences de matériel (capteurs) et de conditions météorologiques locales.

Collecte de nouvelles données

L'un des rôles de la station de base est de stocker les données entrantes de la station météo dans la base de données pour un traitement ultérieur. Pour démarrer le processus qui écoute le port série et stocke dans la base de données, exécutez simplement :

conda activate weatherpython serial_listener.py# toutes les 10 minutes, vous devriez voir les données de la station météo arriver :[Sensor:type(temperature), value(14.3)][Sensor:type(pressure), value( 1056.0)]... 

Générer le modèle de prédiction

Je suppose que vous avez importé mes données ou que vous avez « exécuté le script pendant quelques années » pour rassembler vos données personnalisées. Dans cette étape, nous traiterons donc les données pour créer un modèle utilisé pour prédire les pluies futures.

conda activate weatherpython train.py --days_behind 600 --test-file-percent 10 --datapoints-behind 8 --hour-granularity 6 

* Le premier paramètre --days_behind indique la quantité de données dans le passé que le script doit traiter. Il se mesure en jours

* --test-file-percent signifie quelle quantité de données doit être prise en compte à des fins de test, il s'agit d'une étape régulière dans un algorithme d'apprentissage automatique

* --hour-granularity signifie essentiellement combien d'heures dans le futur nous voudrons la prédiction

* --datapoints-behind ce paramètre sera discuté plus loin dans la section suivante

Afficher des graphiques de données avec tous les capteurs de la station météo

Disons pour les 10 derniers jours :

conda activer les graphiques python météo --days-behind 10 

Prévoyez s'il pleuvra dans la prochaine période

Nous allons prédire s'il va pleuvoir et envoyer un e-mail de notification

conda activate météo python predict.py --datapoints-behind 8 --hour-granularity 6 --from-addr a_gmail_address --from-password gmail_password --to-addr a_email_destination 

Exécutez une prédiction par lot sur les données de test :

python predict_batch.py ​​-f sample_data/test_data.csv 

Il est important d'utiliser les mêmes paramètres que dans le script de train ci-dessus.

Pour que la notification par e-mail fonctionne, connectez-vous à votre compte Gmail et activez Autoriser les applications moins sécurisées. Sachez que cela permet aux autres d'accéder plus facilement à votre compte.

Vous aurez besoin de deux adresses e-mail, d'une adresse Gmail avec l'option ci-dessus activée et d'une autre adresse où vous recevrez votre notification.

Si vous aimez recevoir des notifications toutes les heures, mettez le script dans crontab

Pour voir comment tout cela est possible, passez à l'étape suivante

Étape 6 :Comment ça marche

Dans cette dernière étape, nous aborderons plusieurs aspects de l'architecture de ce projet :

1. Présentation du projet, nous discuterons de l'architecture générale et des technologies impliquées

2. Concepts de base de l'apprentissage automatique

3. Comment les données sont préparées (l'étape la plus importante)

4. Fonctionnement de l'API de wrapper de réseau neuronal (Keras)

5. Améliorations futures

Je vais essayer de donner un exemple de code ici, mais gardez à l'esprit qu'il ne s'agit pas à 100% du code du projet. Dans le projet c'est le code c'est un peu plus compliqué avec des classes et une structure

1. Présentation du projet, nous discuterons de l'architecture générale et des technologies impliquées

Comme nous en avons parlé plus tôt, le projet comporte deux parties distinctes. La station météo elle-même dont la seule fonction est de collecter et de transmettre des données. Et la station de base où se dérouleront tous les entraînements et prédictions de collecte.

Avantages de la séparation de la station météo et de la station de base :

  • besoins en énergie, si la station météorologique était également capable de traiter les données, elle aurait besoin d'une puissance importante, peut-être de grands panneaux solaires ou une source d'alimentation permanente
  • portabilité, en raison de sa petite taille, la station météo peut collecter des données à quelques centaines de mètres et vous pouvez facilement changer son emplacement si nécessaire
  • évolutivité, vous pouvez augmenter la précision des prévisions en construisant plusieurs stations météorologiques et en les répartissant sur quelques centaines de mètres
  • faible coût, car c'est un appareil bon marché, vous pouvez facilement en construire un autre en cas de perte ou de vol

Le choix de la base de données . J'ai choisi mongoDb car ses fonctionnalités sont intéressantes :API sans schéma, gratuite et facile à utiliser

Chaque fois que les données du capteur sont reçues, les données sont enregistrées dans la base de données, une entrée de données ressemble à ceci :

{ "_id" :"04_27_2017_06_17", "humidité" :65, "date" :ISODate("2017-04-27T06:17:18Z"), "pression" :1007, "temperature" :9, "pluie" :0, "lumière" :15} 

La base de données stocke les données au format BSON (similaire à JSON) afin qu'elles soient faciles à lire et à utiliser. J'ai agrégé les données sous un identifiant qui contient la date formatée sous forme de chaîne aux minutes, donc le plus petit regroupement ici est une minute.

La station météo (lorsqu'elle fonctionne correctement) transmettra un point de données toutes les 10 minutes. Un point de données est une collection de valeurs "date", "humidité", "pression", "température", "pluie" et "lumière".

Le traitement des données et le réseau de neurones choix technologique

J'ai choisi Python pour le backend car de nombreuses innovations majeures dans les réseaux de neurones se trouvent dans Python. Une communauté grandissante avec de nombreux référentiels Github, des blogs de tutoriels et des livres est là pour vous aider.

* Pour la partie informatique j'ai utilisé Pandas (https://pandas.pydata.org/ ) . Les pandas facilitent le travail avec les données. Vous pouvez charger des tableaux à partir de structures de données CSV, Excel, Python et les réorganiser, supprimer des colonnes, ajouter des colonnes, indexer par colonne et de nombreuses autres transformations.

* Pour travailler avec les réseaux de neurones, j'ai choisi Keras (https://keras.io/). Keras est un wrapper de réseau neuronal de haut niveau sur des API de niveau plus bas comme Tensorflow et on peut construire un réseau neuronal multicouche avec une douzaine de lignes de code ou plus. C'est un grand avantage parce que nous pouvons construire quelque chose d'utile sur l'excellent travail des autres. Eh bien, c'est l'essentiel de la programmation, construit sur d'autres blocs de construction plus petits.

2. Concepts de base de l'apprentissage automatique

La portée de ce tutoriel n'est pas d'enseigner l'apprentissage automatique, mais simplement de décrire l'un de ses cas d'utilisation possibles et comment nous pouvons l'appliquer concrètement à ce cas d'utilisation.

Les réseaux de neurones sont des structures de données qui ressemblent à des cellules cérébrales appelées neurones. La science a découvert qu'un cerveau a des cellules spéciales appelées neurones qui communiquent avec d'autres neurones par des impulsions électriques à travers des "lignes" appelées axones. S'ils sont suffisamment stimulés (à partir de nombreux autres neurones), les neurones déclencheront une impulsion électrique plus loin dans ce "réseau" stimulant d'autres neurones. C'est bien sûr une simplification excessive du processus, mais fondamentalement, les algorithmes informatiques essaient de reproduire ce processus biologique.

Dans les réseaux de neurones informatiques, chaque neurone a un "point de déclenchement" où, s'il est stimulé sur ce point, il propagera la stimulation vers l'avant, sinon ce ne sera pas le cas. Pour cela chaque neurone simulé aura un biais, et chaque axone un poids. Après une initialisation aléatoire de ces valeurs, un processus appelé « apprentissage » démarre, ce qui signifie qu'en boucle, un algorithme effectuera les étapes suivantes :

  • stimuler les neurones d'entrée
  • propager les signaux à travers les couches du réseau jusqu'aux neurones de sortie
  • lisez les neurones de sortie et comparez les résultats avec les résultats souhaités
  • ajustez les poids des axones pour un meilleur résultat la prochaine fois
  • recommencer jusqu'à ce que le nombre de boucles soit atteint

Si vous souhaitez en savoir plus sur ce processus, vous pouvez consulter cet article :https://mattmazur.com/2015/03/17/a-step-by-step-ba.... Il existe également de nombreux livres et tutoriels disponibles.

Encore une chose, ici nous utiliserons une méthode d'apprentissage supervisé. Cela signifie que nous allons également enseigner à l'algorithme les entrées et les sorties, de sorte qu'étant donné un nouvel ensemble d'entrées, il puisse prédire la sortie.

3. Comment les données sont préparées (l'étape la plus importante)

Dans de nombreux problèmes d'apprentissage automatique et de réseau neuronal, la préparation des données est une partie très importante et couvrira :

  • obtenir les données brutes
  • nettoyage des données :cela signifie la suppression des valeurs orphelines, des aberrations ou d'autres anomalies
  • regroupement de données :prendre de nombreux points de données et les transformer en un point de données agrégé
  • amélioration des données : ajout d'autres aspects des données dérivés de vos propres données ou de sources externes
  • fractionner les données dans les données de train et de test
  • diviser chacune des données d'apprentissage et de test en entrées et sorties. Typically a problem will have many inputs and a few outputs
  • rescale the data so it's between 0 and 1 (this will help the network removing high/low value biases)

Getting the raw data

In our case getting data for MongoDb in python is really easy. Given our datapoints collection just this lines of code will do

client =MongoClient(host, port).weather.datapoints cursor =client.find( {'$and' :[ {'date' :{'$gte' :start_date}}, {'date' :{'$lte' :end_date}} ]} )data =list(cursor).. 

Data cleanup

The empty values in the dataframe are dropped

dataframe =dataframe.dropna() 

Data grouping &data enhancing

This is a very important step, the many small datapoins will be grouped into intervals of 6 hours. For each group several metrics will be calculated on each of the sensors (humidity, rain, temperature, light, pressure)

  • min value
  • max value
  • mean
  • 70, 90, 30, 10 percentiles
  • nr of times there has been a rise in a sensor
  • nr of times there has been a fall in a sensor
  • nr of times there has been steady values in a sensor

All of these things will give the network information for a datapoint, so for each of the 6 hours intervals these things will be known.

From a dataframe that looks like this:

_id date humidity light pressure rain temperature 04_27_2017_03_08 2017-04-27 03:08:36 67.0 0.0 1007.0 0.0 11.004_27_2017_03_19 2017-04-27 03:19:05 66.0 0.0 1007.0 0.0 11.004_27_2017_03_29 2017-04-27 03:29:34 66.0 0.0 1007.0 0.0 11.0  

And the transformation will be:"

_id date humidity_10percentile humidity_30percentile humidity_70percentile humidity_90percentile humidity_avg ... temperature_avg temperature_fall temperature_max temperature_min temperature_rise temperature_steady ... 04_27_2017_0 2017-04-27 03:08:36 59.6 60.8 63.2 66.0 62.294118 ... 10.058824 2 11.0 9.0 1 1404_27_2017_1 2017-04-27 06:06:50 40.3 42.0 60.0 62.0 50.735294 ... 14.647059 3 26.0 9.0 11 2004_27_2017_2 2017-04-27 12:00:59 36.0 37.0 39.8 42.0 38.314286 ... 22.114286 1 24.0 20.0 5 29  

After this a new column named "has_rain" will be added. This will be the output (our predicted variable). Has rain will be 0 or 1 depending if the rain average is above a threshold (0.1). With pandas it's as simple as:

dataframe.insert(loc=1, column='has_rain', value=numpy.where(dataframe['rain_avg']> 0.1, 1, 0)) 

Data cleanup (again)

- we'll drop the date column because it's no use to us, and also remove datapoints where the minimum temperature is below 0 because our weather station it doesn't have a snow sensor, so we won't be able to measure if it snowed

dataframe =dataframe.drop(['date'], axis=1)dataframe =dataframe[dataframe['temperature_min']>=0] 

Data enhancing

Because data in the past might influence our prediction of the rain, we need for each of the dataframe rows to add columns reference to the past rows. This is because each of the row will serve as a training point, and if we want the prediction of the rain to take into account previous datapoints that's exactly what we should do:add more columns for datapoints in the past ex:

_id has_rain humidity_10percentile humidity_30percentile humidity_70percentile humidity_90percentile ... temperature_steady_4 temperature_steady_5 temperature_steady_6 temperature_steady_7 temperature_steady_8 ... 04_27_2017_3 0 36.0 44.8 61.0 63.0 ... NaN NaN NaN NaN NaN04_28_2017_0 0 68.0 70.0 74.0 75.0 ... 14.0 NaN NaN NaN NaN04_28_2017_1 0 40.0 45.0 63.2 69.0 ... 20.0 14.0 NaN NaN NaN04_28_2017_2 0 34.0 35.9 40.0 41.0 ... 29.0 20.0 14.0 NaN NaN04_28_2017_3 0 36.1 40.6 52.0 54.0 ... 19.0 29.0 20.0 14.0 NaN04_29_2017_0 0 52.0 54.0 56.0 58.0 ... 26.0 19.0 29.0 20.0 14.004_29_2017_1 0 39.4 43.2 54.6 57.0 ... 18.0 26.0 19.0 29.0 20.004_29_2017_2 1 41.0 42.0 44.2 47.0 ... 28.0 18.0 26.0 19.0 29.0  

So you see that for every sensor let's say temperature the following rows will be added:"temperature_1", "temperature_2".. meaning temperature on the previous datapoint, temperature on the previous two datapoints etc. I've experimented with this and I found that a optimum number for our 6 hour groupings in 8. That means 8 datapoints in the past (48 hours). So our network learned the best from datapoins spanning 48 hours in the past.

Data cleanup (again)

As you see, the first few columns has "NaN" values because there is nothing in front of them so they should be removed because they are incomplete.

Also data about current datapoint should be dropped, the only exception is "has_rain". the idea is that the system should be able to predict "has_rain" without knowing anything but previous data.

Splitting the data in train and test data

This is very easy due to Sklearn package:

from sklearn.model_selection import train_test_split ...main_data, test_data =train_test_split(dataframe, test_size=percent_test_data) ... 

This will split the data randomly into two different sets

Split each of the train and test data into inputs and outputs

Presuming that our "has_rain" interest column is located first

X =main_data.iloc[:, 1:].valuesy =main_data.iloc[:, 0].values  

Rescale the data so it's between 0 and 1

Again fairly easy because of sklearn

from sklearn.preprocessing import StandardScalerfrom sklearn.externals import joblib..scaler =StandardScaler()X =scaler.fit_transform(X) ...# of course we should be careful to save the scaled model for later reusejoblib.dump(scaler, 'model_file_name.save')  

4. How the actual neural network wrapper API works (Keras)

Building a multi layer neural network with Keras is very easy:

from keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import Dropout ...input_dimensions =X.shape[1] optimizer ='rmsprop'dropout =0.05model =Sequential()inner_nodes =int(input_dimensions / 2)model.add(Dense(inner_nodes, kernel_initializer='uniform', activation='relu', input_dim=input_dimensions))model.add(Dropout(rate=dropout))model.add(Dense(inner_nodes, kernel_initializer='uniform', activation='relu'))model.add(Dropout(rate=dropout))model.add(Dense(1, kernel_initializer='uniform', activation='sigmoid'))model.compile(optimizer=optimizer, loss='mean_absolute_error', metrics=['accuracy']) model.fit(X, y, batch_size=1, epochs=50)...# save the model for later useclassifier.save('file_model_name') 

So what does this code mean? Here we're building a sequential model, that means sequentially all the layers will be evaluated.

a) we declare the input layer (Dense), here all the inputs from our dataset will be initializedm so the "input_dim" parameter must be equal to the row length

b) a Dropout layer is added. To understand the Dropout first we must understand what "overfitting" means:it's a state in which the network has learned too much particularities for a specific dataset and will perform badly when confronted to a new dataset. The dropout layer will disconnect randomly neurons at each iteration so the network won't overfit.

c) another layer of Dense is added

d) another Dropout

e) the last layer is added with one output dimension (it will predict only yes/no)

f) the model is "fitted" that means the learning process will begin, and the model will learn

Other parameters here:

  • activation functions (sigmoid, relu). This are functions that dictate when the neuron will transmit it's impulse further in the network. There are many, but sigmoid and relu are the most common. Check out this link for more details:https://towardsdatascience.com/activation-function...
  • kernel_initializer function (uniform). This means that all the weights are initialized with random uniform values
  • loss function (mean_absolute_error). This function measures the error comparing the network predicted result versus the ground truth. There are many alternatives:https://keras.io/losses/
  • metrics function (accuracy). It measures the performance of the model
  • optimiser functions (rmsprop). It optimizes how the model learn through backpropagation.
  • batch_size. Number of datapoints to take once by Keras before applying optimizer function
  • epochs:how many times the process it's started from 0 (to learn better)

There is no best configuration for any network or dataset, all these parameters can an should be tuned for optimal performance and will make a big difference in prediction success.

5. Future improvements

Let's start from the weather station , I can see a lot of improving work to be done here:

  • add a wind speed / direction sensor. This could be a very important sensor that i'm missing in my model
  • experiment with UV rays, gas and particle sensors
  • add at least two stations in the zone for better data (make some better averages)
  • collect a few more years of data, i've experimented with just a year and a half

Some processing improvements:

  • try to incorporate data from other sources into the model. You can start to import wind speed data and combine with the local station data for a better model. This website offers historical data:https://www.wunderground.com/history/
  • optimize the Keras model better by adjusting:layers, nr of neurons in layers, dropout percents, metrics functions, optimiser functions, loss functions, batch size, learning epochs
  • try other model architectures, for example i've experimented with LSTM (long short term memory) but it gived slightly poorer results)

To try different parameters on the learning model you can use

python train.py --days_behind 600 --test-file-percent 10 --datapoints-behind 6 --hour-granularity 6 --grid-search 

This will search through different "batch_size", "epoch", "optimizer" and "dropout" values, evaluate all and print out the best combination for your data.

If you have some feedback on my work please share it, thanks for staying till the end of the tutorial!

Step 7:Bonus:Using an Official Weather Dataset

I was wondering if I can get better results with a more reliable weather station, so i've searched a bit, and i've came across "Darksky AP I" (https://darksky.net/dev), this is a great tool that provides current and historical weather data with many more sensor data:

  • temperature
  • humidity
  • pressure
  • wind speed
  • wind gust
  • ub index
  • visibilitySo this beeing data from an official weather station, and having more parameters I thought it should perform better so i've gave it a try. To replicate my findings:

1.Download the data from darsky or import my MongoDb collection:

a) Download

  • to download your self, first create an account in darsky and get the API key
  • replace the API key in download_import/config.py
  • also in the config replace the geographic coordonates for the location you want to predict the rain
  • in a console activate "weather" anaconda environment and run:
python download_import/darksky.py -d 1000 

- the free version of the API is limited to 1000 requests per day so if you want more data you need to wait for a longer time

b) Import my downloaded data for Bucharest city

- in a console run

mongoimport -d weather -c darksky --file sample_data/darksky.json  

2. When you train the model specify that it should run on "darksy" dataset

python train.py -d 2000 -p 20 -dp 4 -hg 6 --data-source darksky 

3. To see the results run predict batch script as before

python predict_batch.py -f sample_data/test_data.csv 

You'll see that the overall prediction percent has gone from about 80% to 90%. Also the prediction accuracy when accounting only rainy days has gone up.

So yes, the dataset really matters.

Code

  • Extrait de code 2
  • Extrait de code n°5
  • Code snippet #6
  • Code snippet #10
  • Code snippet #15
  • Code snippet #16
  • Code snippet #18
  • Code snippet #22
  • Code snippet #23
  • Code snippet #25
  • Code snippet #26
Extrait de code #2Texte brut
#include "LowPower.h"
#include "SoftwareSerial.h"#include "Wire.h"#include "Adafruit_Sensor.h"#include "Adafruit_BME280.h"#include "BH1750.h"SoftwareSerial serialComm(4, 5); // RX, TXAdafruit_BME280 bme; BH1750 lightMeter;const byte rainPin =A0;byte sensorsCode =1;/** * voltage level that will pun the microcontroller in deep sleep instead of regular sleep */int voltageDeepSleepThreshold =4200; const byte peripherialsPowerPin =6;char buffer[] ={' ',' ',' ',' ',' ',' ',' '};struct sensorData { byte humidity; int temperature; byte rain; int pressure; long voltage; int light; };sensorData sensors;void setup() { Serial.begin(9600); serialComm.begin(9600); pinMode(peripherialsPowerPin, OUTPUT); digitalWrite(peripherialsPowerPin, HIGH); retard (500); if (!bme.begin()) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1) { customSleep(100); } } Serial.println("Initialization finished succesfully"); retard (50); digitalWrite(peripherialsPowerPin, HIGH);}void loop() { updateSenzors(); transmitData(); customSleep(75); }void updateSenzors() { bme.begin(); lightMeter.begin(); delay(300); sensors.temperature =bme.readTemperature(); sensors.pressure =bme.readPressure() / 100.0F; sensors.humidity =bme.readHumidity(); sensors.light =lightMeter.readLightLevel(); sensors.voltage =readVcc(); sensors.rain =readRain();}void transmitData(){ emptyIncommingSerialBuffer(); Serial.print("Temp:");Serial.println(sensors.temperature); Serial.print("Humid:");Serial.println(sensors.humidity); Serial.print("Pressure:");Serial.println(sensors.pressure); Serial.print("Light:");Serial.println(sensors.light); Serial.print("Voltage:");Serial.println(sensors.voltage); Serial.print("Rain:");Serial.println(sensors.rain); transmitSenzorData("T", sensors.temperature); transmitSenzorData("H", sensors.humidity); transmitSenzorData("PS", sensors.pressure); transmitSenzorData("L", sensors.light); transmitSenzorData("V", sensors.voltage); transmitSenzorData("R", sensors.rain);}void emptyIncommingSerialBuffer(){ while (serialComm.available()> 0) { serialComm.read(); delay(5); }}void transmitSenzorData(String type, int value){ serialComm.print(type); serialComm.print(sensorsCode); serialComm.print(":"); serialComm.print(value); serialComm.print("|"); delay(50);}void customSleep(long eightSecondCycles){ if (sensors.voltage> voltageDeepSleepThreshold) { delay(eightSecondCycles * 8000); retourner; } digitalWrite(peripherialsPowerPin, LOW); for (int i =0; i
Extrait de code n°5Texte brut
cd weather-predict # create anaconda environment named "weather" with python 3.6.2conda create --name weather python=3.6.2 # activate environmentconda activate weather# install all packages pip install -r requirements.txt 
Code snippet #6Plain text
mongodb ={ 'host':'localhost', 'port':27017}...
Code snippet #10Plain text
conda activate weatherpython serial_listener.py# every 10 minutes you should see data from the weather station coming in :[Sensor:type(temperature), value(14.3)][Sensor:type(pressure), value(1056.0)]...
Code snippet #15Plain text
{ "_id" :"04_27_2017_06_17", "humidity" :65, "date" :ISODate("2017-04-27T06:17:18Z"), "pressure" :1007, "temperature" :9, "rain" :0, "light" :15}
Code snippet #16Plain text
client =MongoClient(host, port).weather.datapoints cursor =client.find( {'$and' :[ {'date' :{'$gte' :start_date}}, {'date' :{'$lte' :end_date}} ]} )data =list(cursor)..
Code snippet #18Plain text
_id date humidity light pressure rain temperature 04_27_2017_03_08 2017-04-27 03:08:36 67.0 0.0 1007.0 0.0 11.004_27_2017_03_19 2017-04-27 03:19:05 66.0 0.0 1007.0 0.0 11.004_27_2017_03_29 2017-04-27 03:29:34 66.0 0.0 1007.0 0.0 11.0 
Code snippet #22Plain text
_id has_rain humidity_10percentile humidity_30percentile humidity_70percentile humidity_90percentile ... temperature_steady_4 temperature_steady_5 temperature_steady_6 temperature_steady_7 temperature_steady_8 ... 04_27_2017_3 0 36.0 44.8 61.0 63.0 ... NaN NaN NaN NaN NaN04_28_2017_0 0 68.0 70.0 74.0 75.0 ... 14.0 NaN NaN NaN NaN04_28_2017_1 0 40.0 45.0 63.2 69.0 ... 20.0 14.0 NaN NaN NaN04_28_2017_2 0 34.0 35.9 40.0 41.0 ... 29.0 20.0 14.0 NaN NaN04_28_2017_3 0 36.1 40.6 52.0 54.0 ... 19.0 29.0 20.0 14.0 NaN04_29_2017_0 0 52.0 54.0 56.0 58.0 ... 26.0 19.0 29.0 20.0 14.004_29_2017_1 0 39.4 43.2 54.6 57.0 ... 18.0 26.0 19.0 29.0 20.004_29_2017_2 1 41.0 42.0 44.2 47.0 ... 28.0 18.0 26.0 19.0 29.0 
Code snippet #23Plain text
from sklearn.model_selection import train_test_split ...main_data, test_data =train_test_split(dataframe, test_size=percent_test_data) ...
Code snippet #25Plain text
from sklearn.preprocessing import StandardScalerfrom sklearn.externals import joblib..scaler =StandardScaler()X =scaler.fit_transform(X) ...# of course we should be careful to save the scaled model for later reusejoblib.dump(scaler, 'model_file_name.save') 
Code snippet #26Plain text
from keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import Dropout ...input_dimensions =X.shape[1] optimizer ='rmsprop'dropout =0.05model =Sequential()inner_nodes =int(input_dimensions / 2)model.add(Dense(inner_nodes, kernel_initializer='uniform', activation='relu', input_dim=input_dimensions))model.add(Dropout(rate=dropout))model.add(Dense(inner_nodes, kernel_initializer='uniform', activation='relu'))model.add(Dropout(rate=dropout))model.add(Dense(1, kernel_initializer='uniform', activation='sigmoid'))model.compile(optimizer=optimizer, loss='mean_absolute_error', metrics=['accuracy']) model.fit(X, y, batch_size=1, epochs=50)...# save the model for later useclassifier.save('file_model_name')
Github
https://github.com/claws/BH1750https://github.com/claws/BH1750
Github
https://github.com/rocketscream/Low-Powerhttps://github.com/rocketscream/Low-Power
Github
https://github.com/adafruit/Adafruit_Sensorhttps://github.com/adafruit/Adafruit_Sensor
Github
https://github.com/adafruit/Adafruit_BME280_Libraryhttps://github.com/adafruit/Adafruit_BME280_Library
Github
https://github.com/danionescu0/home-automationhttps://github.com/danionescu0/home-automation

Schémas

sketch_KAtDa2VReF.fzz
Weather station arduino sketch
https://github.com/danionescu0/home-automation/tree/master/arduino-sketches/weatherStation

Processus de fabrication

  1. Capteur de température Python et Raspberry Pi
  2. Console d'édition Photoshop DIY utilisant Arduino Nano RP 2040
  3. Python Renommer le fichier et le répertoire à l'aide de os.rename()
  4. Système de présence utilisant Arduino et RFID avec Python
  5. Télécommande universelle utilisant Arduino, 1Sheeld et Android
  6. Voltmètre DIY utilisant Arduino et Smartphone
  7. Capteur de rythme cardiaque infrarouge DIY utilisant Arduino
  8. Mesure de la fréquence et du cycle de service à l'aide d'Arduino
  9. Voltmètre DIY avec Arduino et un écran Nokia 5110