Prediksi Curah Hujan Akurat: Bangun Sistem Berbasis Arduino dengan Python & Keras
Komponen dan Perlengkapan
- Kotak plastik kecil dengan tutup yang dapat dilepas – 1
- Holder baterai tiga AAA – 1
- Baterai AAA rechargeable tiga – 1
- Panel surya kecil 6V – 1
- SparkFun Arduino Pro Mini 328 - 5V/16MHz – 1
- Dioda 1N4004 – 1
- Transistor NPN Tujuan Umum – 1
- Sensor hujan – 1
- Modul komunikasi serial HC-12 – 1
- Modul serial USB HC-12 – 1
- Modul sensor atmosferik BME280 – 1
- Modul pencahayaan BH1750 – 1
- PCB, kabel, solder, konektor schru KF301-2P, konektor PCB pria&wanita, lem – 1
- Regulator 3.3V – 1
Alat yang Diperlukan
- Adapter USB ke serial FTDI FT232RL
- Bor
- Pengelasan
- Obeng
Tentang Proyek Ini
Tujuan besar di sini jelas untuk memprediksi hujan di masa depan (kita akan mencoba 6 jam). Prediksi akan berupa ya atau tidak (boolean dalam istilah pemrograman). Saya telah mencari tutorial tentang hal ini dan tidak menemukan satu pun yang lengkap di setiap aspek. Jadi milik saya akan membawa ini ke pendekatan yang baru sepenuhnya dan memasuki setiap aspeknya. Untuk itu kita akan:
- Membangun stasiun cuaca kita sendiri. Stasiun harus sepenuhnya off-grid dengan panel surya, dan mode energi rendah yang sangat (beberapa puluhan microampere per jam)
- Memprogram stasiun sehingga mengumpulkan data dan mentransmisinya setiap sepuluh menit ke stasiun dasar
- Mengumpulkan data di stasiun dasar dan menyimpannya (dalam database)
- Menggunakan jaringan saraf tiruan (library Keras) dan library Python lainnya seperti pandas untuk memfilter, membersihkan, dan memproses data, lalu memberikannya ke jaringan saraf untuk melatih "model" untuk memprediksi apakah akan hujan atau tidak
- Terakhir memprediksi apakah akan hujan atau tidak dalam 6 jam ke depan dan memberitahukan pengguna melalui email
Saya secara pribadi telah menggunakan stasiun cuaca ini untuk mengumpulkan data (Anda dapat mengunduh data di langkah berikutnya jika Anda inginkan). Dengan hanya sekitar 600 hari data cuaca, sistem dapat membuat prediksi apakah akan hujan atau tidak dalam 6 jam ke depan dengan akurasi sekitar 80% tergantung pada parameter yang tidak buruk.
Tutorial ini akan membawa Anda melalui semua langkah yang diperlukan untuk memprediksi hujan dari nol. Kami akan membuat produk akhir yang melakukan pekerjaan praktis, tanpa menggunakan API cuaca atau machine learning eksternal. Kami akan belajar di tengah jalan cara membangun stasiun cuaca praktis (rendah daya dan off-grid) yang benar-benar mengumpulkan data selama periode waktu yang lama tanpa pemeliharaan. Setelah itu Anda akan belajar cara memprogramnya menggunakan Arduino IDE. Cara mengumpulkan data ke dalam database di stasiun dasar (server). Dan cara memproses data (Pandas) dan menerapkan jaringan saraf tiruan (Keras) lalu memprediksi hujan.
Langkah 1: Komponen dan Alat untuk Membangun Stasiun
Komponen:
- Kotak plastik kecil dengan tutup yang dapat dilepas (milik saya memiliki baut). Ukuran kotak harus cukup besar untuk menempatkan komponen kecil dan baterai. Kotak saya berukuran 11 x 7 x 5 cm
- Holder baterai tiga AAA
- Baterai AAA rechargeable tiga
- Panel surya kecil 6V
- Arduino Pro Mini 328p
- Dioda, 1N4004 (untuk mencegah arus balik dari baterai ke panel)
- Transistor NPN kecil dan resistor 1k (untuk mengalihkan daya ke komponen nyala dan mati)
- Sensor hujan
- Modul komunikasi serial HC-12
- Modul serial USB HC-12 (untuk stasiun dasar)
- Modul sensor BME280 Bosch (untuk kelembaban, suhu, tekanan)
- Modul pencahayaan BH1750
- PCB, kabel, solder, konektor schru KF301-2P, konektor PCB pria&wanita, lem
- Regulator 3.3V
- Stasiun dasar: PC, atau papan pengembangan yang berjalan terus-menerus. Perannya mengumpulkan data, melatih model prediksi hujan, dan membuat prediksi
Alat:
- Adapter USB ke serial FTDI FT232RL untuk memprogram Arduino Pro Mini
- Arduino IDE
- Bor
- Gergaji halus
- Obeng
- Pengelasan
- Pemotong kabel
Langkah 2: Membangun Stasiun Cuaca
Stasiun cuaca terdiri dari kumpulan komponen berikut:
1. kotak dengan panel surya yang ditempel padanya
2. PCB dengan elektronika di dalamnya
3. holder baterai juga di dalamnya
4. sensor BME280, cahaya, dan hujan di luar
1. Kotak membutuhkan 4 lubang, satu untuk kabel panel surya, tiga lainnya untuk sensor yang akan ditempatkan di luar. Pertama bor lubang-lubang, harus cukup besar untuk kabel pria-wanita untuk keluar dan pergi ke sensor. Setelah lubang dibuat, tempel panel ke satu sisi kotak dan masukkan kabelnya melalui lubang ke dalam
2. PCB akan menahan Arduino, HC-12, regulator 3.3V, dioda, transistor, resistor dan dua KF301-2P
- pertama selangir dua konektor PCB wanita pada PCB untuk Arduino, selangir konektor PCB pria ke Arduino dan tempatkan Arduino pada PCB
- LED Arduino harus dilepaskan atau setidaknya salah satu pin-nya. Ini sangat penting karena LED akan menghabiskan daya dalam jumlah besar. Hati-hati untuk tidak merusak komponen lain
- selangir transistor, resistor, dan regulator 3.3V
- selangir dua KF301-2P. Satu akan untuk panel surya, yang lain untuk holder baterai
- selangir tiga konektor PCB wanita: untuk sensor cahaya, BME280 dan sensor hujan
- selangir kabel kecil untuk menghubungkan semua komponen PCB (periksa gambar dan skematik fritzing)
3. tempatkan 3 baterai NiMH AAA yang terisi di dalam holder dan tempatkan di dalam kotak, menghubungkan kabel ke konektor KF301-2P
4. hubungkan sensor BME280 dan cahaya dari luar kotak ke konektor pria yang sesuai
Untuk sensor hujan, selangir tiga kabel (Gnd, Vcc, signal) padanya, dan ke sisi lain selangir pin pria yang akan pergi ke dalam kotak ke konektor pria yang sesuai
Hal terakhir adalah menempatkan stasiun ke posisinya akhir. Saya memilih posisi yang terlindung dari hujan dan salju. Saya memilih kabel yang lebih panjang untuk sensor hujan dan menempatkannya terpisah di hujan pada penopang yang stabil. Untuk kotak utama saya memilih jenis lem khusus dengan perekat (periksa gambar) tetapi apa pun yang memegang kotak akan cukup.
Langkah 3: Kode Arduino
Pada langkah ini Anda akan mempelajari library eksternal apa yang diperlukan, kita akan meninjau kode dan cara kerjanya dan tentu saja Anda akan dapat mengunduhnya atau menyalin-tempelkannya ke Arduino IDE dan mengunggahnya ke stasiun cuaca.
Peran stasiun cuaca adalah untuk mentransmisikan ke stasiun dasar setiap 10 menit data tentang sensor-sensor-nya.
Pertama mari kita jelaskan apa yang dilakukan program stasiun cuaca:
1. membaca data sensor (kelembaban, suhu, tekanan, hujan, cahaya, tegangan)
2. mentransmisikan data yang terenkode melalui baris serial perangkat lunak kedua.
Data yang terenkode terlihat seperti ini:
H1:78|T1:12|PS1:1022|L1:500|R1:0|V1:4010|
Pernyataan di atas akan berarti bahwa: kelembaban dari stasiun "1" adalah 78 persen, suhu dari stasiun 1 adalah 12 derajat, tekanan adalah 1022 bar, tingkat cahaya 500 lux, hujan 0, dan tegangan 4010 milivolt
3. matikan daya komponen tambahan: sensor dan perangkat komunikasi
4. memasukkan Arduino ke mode tidur selama 10 menit (ini akan membuatnya mengkonsumsi kurang dari 50 microampere)
5. nyalakan komponen dan ulangi langkah 1 - 4
Satu tweak kecil di sini, jika tingkat tegangan di atas 4.2 V Arduino akan menggunakan fungsi tidur normal "delay(milliseconds)". Ini akan sangat meningkatkan konsumsi daya dan menurunkan tegangan dengan cepat. Ini secara efektif mencegah panel surya dari pengisian daya berlebihan pada baterai.
Anda dapat mendapatkan kode dari repositori Github saya di sini: https://github.com/danionescu0/home-automation/tre...
Atau menyalin-tempelkannya dari bawah ini, entah bagaimana hapus baris dengan "transmitSenzorData("V", sensors.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, TX Adafruit_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); delay(500); if (!bme.begin()) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1) { customSleep(100); } } Serial.println("Initialization finished succesfully"); delay(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); return; } digitalWrite(peripherialsPowerPin, LOW); for (int i = 0; i < eightSecondCycles; i++) { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); } digitalWrite(peripherialsPowerPin, HIGH); delay(500); } byte readRain() { byte level = analogRead(rainPin); return map(level, 0, 1023, 0, 100); } long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }
Langkah 4: Menyiapkan Stasiun Dasar
Stasiun dasar akan terdiri dari komputer linux (desktop, laptop atau papan pengembangan) dengan modul HC-12 USB yang ditempel. Komputer harus tetap menyala untuk mengumpulkan data setiap 10 menit dari stasiun.
Saya menggunakan laptop saya dengan Ubuntu 18.
Langkah Instalasi:
1. Instal Anaconda. Anaconda adalah manajer paket Python dan akan memudahkan kami untuk bekerja dengan dependensi yang sama. Kami akan dapat mengontrol versi Python, dan setiap versi paket
Jika Anda tidak tahu cara menginstalnya periksa ini: https://www.digitalocean.com/community/tutorials/h... tutorial dan ikuti langkah 1 - 8
2. Instal mongoDb. MongoDb akan menjadi database utama kami untuk proyek ini. Ini akan menyimpan data tentang semua time series sensor. Ini tanpa skema dan untuk tujuan kami mudah digunakan.
Untuk langkah instalasi periksa halaman mereka: https://docs.mongodb.com/v3.4/tutorial/install-mon...
Saya menggunakan versi mongoDb yang lebih lama 3.4.6, jika Anda mengikuti tutorial di atas Anda akan mendapatkannya tepat. Secara prinsipnya harus bekerja dengan versi terbaru.
[Opsional] tambahkan indeks pada kolom tanggal:
mongo use weather db.weather_station.createIndex({"date" : 1})
3. Unduh proyek dari sini: https://github.com/danionescu0/home-automation. Kami akan menggunakan folder weather-predict
sudo apt-get install git git clone https://github.com/danionescu0/home-automation.gi...
4. Buat dan konfigurasikan lingkungan Anaconda:
cd weather-predict # create anaconda environment named "weather" with python 3.6.2 conda create --name weather python=3.6.2 # activate environment conda activate weather # install all packages pip install -r requirements.txt
Ini akan membuat lingkungan Anaconda baru dan menginstal paket yang diperlukan. Beberapa paket adalah:
Keras (lapisan jaringan saraf tingkat tinggi, dengan library ini kami akan membuat semua prediksi jaringan saraf kami)
pandas (alat berguna yang memanipulasi data, kami akan menggunakannya secara intensif)
pymongo (driver Python mongoDb)
sklearn (alat penambangan data dan analisis data)
Konfigurasikan Proyek
File konfigurasi terletak di folder weather-predict dan bernama config.py
1. jika Anda menginstal MongoDb secara jarak jauh atau pada port yang berbeda ubah "host" atau "port" di
mongodb = { 'host': 'localhost', 'port': 27017 } ...
2. Sekarang kita perlu menempelkan adapter serial USB HC-12. Sebelum itu jalankan:
ls -l /dev/tty*
dan Anda akan mendapatkan daftar perangkat yang dipasang.
Sekarang masukkan HC-12 ke port USB dan jalankan perintah yang sama lagi. Harus ada satu entri baru dalam daftar itu, adapter serial kami. Sekarang ubah port adapter dalam konfigurasi jika diperlukan
serial = { 'port': '/dev/ttyUSB0', 'baud_rate': 9600 }
Entri konfigurasi lainnya adalah jalur file default, tidak perlu diubah di sana.
Langkah 5: Menggunakan Stasiun Cuaca dalam Praktik
Di sini kita akan membahas hal dasar tentang impor data uji saya, menjalankan beberapa tes padanya, menyiapkan data Anda sendiri, menampilkan beberapa grafik dan menyiapkan email dengan prediksi untuk beberapa jam ke depan.
Jika Anda ingin tahu lebih banyak tentang cara kerjanya periksa langkah berikutnya "Bagaimana cara kerjanya"
Mengimpor data yang sudah saya kumpulkan
MongoDb datang dengan perintah CLI untuk mengimpor data dari json:
mongoimport -d weather -c weather_station --file sample_data/weather_station.json
Ini akan mengimpor file dari data contoh ke dalam database "weather" dan koleksi "datapoints"
Peringatan di sini, jika Anda menggunakan data yang saya kumpulkan dan menggabungkannya dengan data lokal baru Anda akurasi mungkin menurun karena perbedaan kecil dalam hardware (sensor) dan pola cuaca lokal.
Mengumpulkan data baru
Salah satu peran stasiun dasar adalah menyimpan data masuk dari stasiun cuaca ke dalam database untuk pemrosesan nanti. Untuk memulai proses yang mendengarkan port serial dan menyimpan di database cukup jalankan:
conda activate weather python serial_listener.py # setiap 10 menit Anda seharusnya melihat data dari stasiun cuaca masuk : [Sensor: type(temperature), value(14.3)] [Sensor: type(pressure), value(1056.0)] ...
Menghasilkan model prediksi
Saya akan mengasumsikan Anda telah mengimpor data saya atau "menjalankan skrip selama beberapa tahun" untuk mengumpulkan data pribadi Anda, jadi pada langkah ini kita akan memproses data untuk membuat model yang digunakan untuk memprediksi hujan di masa depan.
conda activate weather python train.py --days_behind 600 --test-file-percent 10 --datapoints-behind 8 --hour-granularity 6
* Parameter pertama --days_behind berarti seberapa jauh ke belakang dalam waktu skrip harus memproses data. Diukur dalam hari
* --test-file-percent berarti seberapa banyak data yang harus dipertimbangkan untuk tujuan pengujian, ini adalah langkah reguler dalam algoritma pembelajaran mesin
* --hour-granularity pada dasarnya berarti berapa jam ke depan kita akan ingin prediksi
* --datapoints-behind parameter ini akan dibahas lebih lanjut di bagian berikutnya
Lihat beberapa grafik data dengan semua sensor stasiun cuaca
Katakanlah untuk 10 hari terakhir:
conda activate weather python graphs --days-behind 10
Memprediksi apakah akan hujan dalam periode berikutnya
Kami akan memprediksi apakah akan hujan dan mengirim email pemberitahuan
conda activate weather python predict.py --datapoints-behind 8 --hour-granularity 6 --from-addr a_gmail_address --from-password gmail_password --to-addr a_email_destination
Jalankan prediksi batch pada data uji:
python predict_batch.py -f sample_data/test_data.csv
Penting untuk menggunakan parameter yang sama seperti dalam skrip train di atas.
Agar pemberitahuan email bekerja masuk ke akun Gmail Anda dan Nyalakan Izinkan aplikasi yang kurang aman. Sadarlah bahwa ini membuat lebih mudah untuk orang lain untuk mendapatkan akses ke akun Anda.
Anda akan membutuhkan dua alamat email, satu alamat Gmail dengan opsi di atas diaktifkan, dan satu alamat lain tempat Anda akan menerima pemberitahuan Anda.
Jika Anda ingin menerima pemberitahuan setiap jam, masukkan skrip ke crontab
Untuk melihat bagaimana semua ini mungkin periksa langkah berikutnya
Langkah 6: Bagaimana Cara Kerjanya
Pada langkah terakhir ini kita akan membahas beberapa aspek dari arsitektur proyek ini:
1. Ringkasan proyek, kita akan membahas arsitektur umum dan teknologi yang terlibat
2. Konsep dasar pembelajaran mesin
3. Bagaimana data dipersiapkan (langkah yang paling penting)
4. Bagaimana API pembungkus jaringan saraf sebenarnya bekerja (Keras)
5. Perbaikan di masa depan
Saya akan mencoba memberikan beberapa contoh kode di sini tetapi ingatlah bahwa itu bukan 100% kode dari proyek. Dalam proyek itu sendiri kodenya sedikit lebih rumit dengan kelas dan struktur
1. Ringkasan proyek, kita akan membahas arsitektur umum dan teknologi yang terlibat
Seperti yang kita bicarakan sebelumnya, proyek ini memiliki dua bagian terpisah. Stasiun cuaca itu sendiri yang fungsinya hanya untuk mengumpulkan dan mentransmisikan data. Dan stasiun dasar di mana semua pengumpulan pelatihan dan prediksi akan terjadi.
Keuntungan pemisahan stasiun cuaca dan stasiun dasar:
- persyaratan daya, jika stasiun cuaca dapat memproses data juga, itu akan membutuhkan daya yang besar, mungkin panel surya besar atau sumber daya permanen
- portabilitas, karena ukurannya kecil stasiun cuaca dapat mengumpulkan data dari beberapa ratus meter jauh dan Anda dapat dengan mudah mengubah tempatnya jika diperlukan
- skalabilitas, Anda dapat meningkatkan akurasi prediksi dengan membangun lebih dari satu stasiun cuaca dan menyebarnya di sekitar beberapa ratus meter
- biaya rendah, karena ini adalah perangkat murah Anda dapat dengan mudah membangun yang lain jika satu hilang atau dicuri
Pilihan database. Saya memilih mongoDb karena fitur-fiturnya yang bagus: tanpa skema, gratis dan mudah digunakan API
Setiap kali data sensor diterima data disimpan di database, entri data terlihat seperti ini:
{ "_id" : "04_27_2017_06_17", "humidity" : 65, "date" : ISODate("2017-04-27T06:17:18Z"), "pressure" : 1007, "temperature" : 9, "rain" : 0, "light" : 15 }
Database menyimpan data dalam format BSON (mirip dengan JSON) jadi mudah dibaca dan mudah digunakan. Saya telah mengagregat data di bawah pengidentifikasi yang berisi tanggal yang diformat sebagai string hingga menit, jadi pengelompokan terkecil di sini adalah satu menit.
Stasiun cuaca (saat bekerja dengan baik) akan mentransmisikan titik data setiap 10 menit. Titik data adalah kumpulan nilai "date", "humidity", "pressure", "temperature", "rain" dan "light".
Pemrosesan data dan teknologi jaringan saraf tiruan
Saya memilih Python untuk backend karena banyak inovasi besar dalam jaringan saraf ditemukan di Python. Komunitas yang tumbuh dengan banyak repositori Github, tutorial blog dan buku ada di sini untuk membantu.
* Untuk bagian pemrosesan data saya telah menggunakan Pandas (https://pandas.pydata.org/). Pandas membuat bekerja dengan data mudah. Anda dapat memuat tabel dari CSV, Excel, struktur data Python dan mengurutkannya ulang, menghapus kolom, menambahkan kolom, mengindeks berdasarkan kolom dan transformasi banyak lainnya.
* Untuk bekerja dengan jaringan saraf saya telah memilih Keras (https://keras.io/). Keras adalah pembungkus jaringan saraf tingkat tinggi atas API tingkat lebih rendah seperti Tensorflow dan seseorang dapat membangun jaringan saraf multi-lapiras dengan beberapa baris kode atau lebih. Ini adalah keuntungan besar karena kita dapat membangun sesuatu yang berguna atas pekerjaan orang lain. Nah ini adalah hal dasar pemrograman, membangun atas blok konstruksi yang lebih kecil.
2. Konsep dasar pembelajaran mesin
Cakupan tutorial ini bukan untuk mengajari pembelajaran mesin, tetapi hanya untuk menggambarkan salah satu kasus penggunaan yang mungkin dan bagaimana kita dapat secara praktis menerapkannya ke kasus penggunaan ini.
Jaringan saraf tiruan adalah struktur data yang mirip dengan sel otak yang disebut neuron. Ilmu pengetahuan menemukan bahwa otak memiliki sel khusus yang disebut neuron yang berkomunikasi dengan neuron lain melalui impuls listrik melalui "garis" yang disebut asson. Jika diragu cukup (dari banyak neuron lain) neuron akan memicu impuls listrik lebih jauh dalam "jaringan" ini meragui neuron lain. Ini tentu merupakan penyederhanaan dari proses, tetapi pada dasarnya algoritma komputer mencoba mereplikasi proses biologis ini.
Dalam jaringan saraf komputer setiap neuron memiliki "titik pemicu" di mana jika diragu melebihi titik itu itu akan menyebarkan raguan ke depan, jika tidak tidak akan. Untuk ini setiap neuron simulasi akan memiliki bias, dan setiap asson bobot. Setelah inisialisasi acak nilai-nilai ini sebuah proses yang disebut "belajar" dimulai ini berarti dalam sebuah loop algoritma akan melakukan langkah-langkah ini:
- sebarkan sinyal melalui lapisan jaringan hingga neuron output
- baca neuron output dan bandingkan hasil dengan hasil yang diinginkan
- sesuaikan bobot asson untuk hasil yang lebih baik lain kali
- mulai lagi sampai jumlah loop tercapai
Jika Anda ingin mengetahui lebih banyak detail tentang proses ini Anda dapat memeriksa artikel ini: https://mattmazur.com/2015/03/17/a-step-by-step-ba.... Ada juga banyak buku dan tutorial di luar sana.
Satu hal lagi, di sini kita akan menggunakan metode pembelajaran terawasi. Itu berarti kita akan mengajarkan algoritma input dan output juga, sehingga diberikan seperangkat input baru itu dapat memprediksi output.
3. Bagaimana data dipersiapkan (langkah yang paling penting)
Dalam banyak masalah pembelajaran mesin dan jaringan saraf tiruan persiapan data adalah bagian yang sangat penting dan akan mencakup:
- pembersihan data: ini akan berarti menghapus nilai yatim piatu, aberansi atau anomali lainnya
- pengelompokan data: mengambil banyak titik data dan mentransformasikannya menjadi titik data agregat
- peningkatan data: menambahkan aspek lain dari data yang berasal dari data sendiri, atau dari sumber eksternal
- memecah data menjadi data pelatihan dan data uji
- memecah masing-masing data pelatihan dan data uji menjadi input dan output. Biasanya masalah akan memiliki banyak input dan beberapa output
- rescale data sehingga antara 0 dan 1 (ini akan membantu jaringan menghapus bias nilai tinggi/rendah)
Mendapatkan data mentah
Dalam kasus kita mendapatkan data untuk MongoDb dalam python sangatlah mudah. Dengan koleksi titik data kita cukup baris kode ini akan dilakukan
client = MongoClient(host, port).weather.datapoints cursor = client.find( {'$and' : [ {'date' : {'$gte' : start_date}}, {'date' : {'$lte' : end_date}} ]} ) data = list(cursor) ..
Pembersihan data
Nilai kosong dalam dataframe dihapus
dataframe = dataframe.dropna()
Pengelompokan data & peningkatan data
Ini adalah langkah yang sangat penting, banyak titik data kecil akan dikelompokkan ke dalam interval 6 jam. Untuk setiap kelompok beberapa metrik akan dihitung pada setiap sensor (kelembaban, hujan, suhu, cahaya, tekanan)
- jumlah kali ada kenaikan pada sensor
- jumlah kali ada penurunan pada sensor
- jumlah kali ada nilai stabil pada sensor
Semua hal ini akan memberi jaringan informasi untuk suatu titik data, jadi untuk setiap interval 6 jam ini akan diketahui.
Dari dataframe yang terlihat seperti ini:
_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.0 04_27_2017_03_19 2017-04-27 03:19:05 66.0 0.0 1007.0 0.0 11.0 04_27_2017_03_29 2017-04-27 03:29:34 66.0 0.0 1007.0 0.0 11.0
Dan transformasi akan menjadi:
_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 14 04_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 20 04_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
Setelah ini kolom baru bernama "has_rain" akan ditambahkan. Ini akan menjadi output (variabel yang diprediksi kita). Hujan akan 0 atau 1 tergantung apakah rata-rata hujan di atas ambang batas (0.1). Dengan pandas ini sederhana seperti:
dataframe.insert(loc=1, column='has_rain', value=numpy.where(dataframe['rain_avg'] > 0.1, 1, 0))
Pembersihan data (lagi)
- kita akan menghapus kolom tanggal karena tidak berguna bagi kami, dan juga menghapus titik data di mana suhu minimum di bawah 0 karena stasiun cuaca kami tidak memiliki sensor salju, jadi kami tidak akan dapat mengukur apakah salju turun
dataframe = dataframe.drop(['date'], axis=1) dataframe = dataframe[dataframe['temperature_min'] >= 0]
Peningkatan data
Karena data di masa lalu mungkin mempengaruhi prediksi kami terhadap hujan, kita perlu untuk setiap baris dataframe menambahkan kolom referensi ke baris di masa lalu. Ini adalah karena setiap baris akan berfungsi sebagai titik pelatihan, dan jika kita ingin prediksi hujan untuk mempertimbangkan titik data sebelumnya itulah yang harus kita lakukan: tambahkan lebih banyak kolom untuk titik data di masa lalu 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 NaN 04_28_2017_0 0 68.0 70.0 74.0 75.0 ... 14.0 NaN NaN NaN NaN 04_28_2017_1 0 40.0 45.0 63.2 69.0 ... 20.0 14.0 NaN NaN NaN 04_28_2017_2 0 34.0 35.9 40.0 41.0 ... 29.0 20.0 14.0 NaN NaN 04_28_2017_3 0 36.1 40.6 52.0 54.0 ... 19.0 29.0 20.0 14.0 NaN 04_29_2017_0 0 52.0 54.0 56.0 58.0 ... 26.0 19.0 29.0 20.0 14.0 04_29_2017_1 0 39.4 43.2 54.6 57.0 ... 18.0 26.0 19.0 29.0 20.0 04_29_2017_2 1 41.0 42.0 44.2 47.0 ... 28.0 18.0 26.0 19.0 29.0
Jadi Anda lihat bahwa untuk setiap sensor katakanlah suhu baris berikut akan ditambahkan: "temperature_1", "temperature_2".. berarti suhu pada titik data sebelumnya, suhu pada dua titik data sebelumnya dll. Saya telah bereksperimen dengan ini dan saya menemukan bahwa jumlah optimum untuk pengelompokan 6 jam kami adalah 8. Itu berarti 8 titik data di masa lalu (48 jam). Jadi jaringan kami belajar paling baik dari titik data yang mencakup 48 jam di masa lalu.
Pembersihan data (lagi)
Seperti yang Anda lihat, beberapa kolom pertama memiliki nilai "NaN" karena tidak ada apa-apa di depannya jadi harus dihapus karena tidak lengkap.
Juga data tentang titik data saat ini harus dihapus, satu-satunya pengecualian adalah "has_rain". Ideanya adalah sistem harus dapat memprediksi "has_rain" tanpa mengetahui apa-apa kecuali data sebelumnya.
Memecah data menjadi data pelatihan dan data uji
Ini sangat mudah karena paket Sklearn:
from sklearn.model_selection import train_test_split ... main_data, test_data = train_test_split(dataframe, test_size=percent_test_data) ...
Ini akan membagi data secara acak menjadi dua set yang berbeda
Memecah masing-masing data pelatihan dan data uji menjadi input dan output
Mengasumsikan bahwa kolom "has_rain" kami terletak pertama
X = main_data.iloc[:, 1:].values y = main_data.iloc[:, 0].values
Rescale data sehingga antara 0 dan 1
Lagi cukup mudah karena sklearn
from sklearn.preprocessing import StandardScaler from sklearn.externals import joblib .. scaler = StandardScaler() X = scaler.fit_transform(X) ... # tentu saja kita harus berhati-hati untuk menyimpan model yang discale untuk digunakan kembali nanti joblib.dump(scaler, 'model_file_name.save')
4. Bagaimana API pembungkus jaringan saraf tiruan sebenarnya bekerja (Keras)
Membangun jaringan saraf tiruan multi-lapiras dengan Keras sangatlah mudah:
from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout ... input_dimensions = X.shape[1] optimizer = 'rmsprop' dropout = 0.05 model = 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 use classifier.save('file_model_name')
Jadi apa arti kode ini? Di sini kita membangun model berurutan, yang berarti semua lapisan akan dievaluasi secara berurutan.
a) kami mendeklarasikan lapisan input (Dense), di sini semua input dari kumpulan data kami akan diinisialisasi, jadi parameter "input_dim" harus sama dengan panjang baris
b) lapisan Dropout ditambahkan. Untuk memahami Dropout pertama kita harus memahami apa arti "overfitting": itu adalah keadaan di mana jaringan telah terlalu banyak mempelajari kesamaan khusus untuk kumpulan data tertentu dan akan berjalan buruk ketika dihadapkan pada kumpulan data baru. Lapisan dropout akan memutuskan neuron secara acak pada setiap iterasi sehingga jaringan tidak akan overfit.
c) lapisan Dense lain ditambahkan
d) Dropout lain
e) lapisan terakhir ditambahkan dengan satu dimensi output (ia hanya akan memprediksi ya/tidak)
f) model "dipesatkan" yang berarti proses pembelajaran akan dimulai, dan model akan belajar
Parameter lain di sini:
- fungsi aktivasi (sigmoid, relu). Ini adalah fungsi yang menentukan kapan neuron akan mentransmisikan impulsnya lebih jauh dalam jaringan. Ada banyak, tetapi sigmoid dan relu adalah yang paling umum. Periksa tautan ini untuk lebih banyak detail: https://towardsdatascience.com/activation-function...
- fungsi kernel_initializer (uniform). Ini berarti semua bobot diinisialisasi dengan nilai acak seragam
- fungsi loss (mean_absolute_error). Fungsi ini mengukur kesalahan membandingkan hasil prediksi jaringan versus kebenaran tanah. Ada banyak alternatif: https://keras.io/losses/
- fungsi metrik (accuracy). Ini mengukur kinerja model
- fungsi optimizer (rmsprop). Ini mengoptimalkan cara model belajar melalui backpropagation.
- batch_size. Jumlah titik data yang diambil oleh Keras sekali sebelum menerapkan fungsi optimizer
- epochs: berapa banyak kali proses dimulai dari 0 (untuk belajar lebih baik)
Tidak ada konfigurasi terbaik untuk jaringan atau kumpulan data apa pun, semua parameter ini dapat dan harus disesuaikan untuk kinerja optimal dan akan membuat perbedaan besar dalam keberhasilan prediksi.
5. Perbaikan di masa depan
Mari kita mulai dari stasiun cuaca, saya bisa melihat banyak pekerjaan perbaikan yang perlu dilakukan di sini:
- tambahkan sensor kecepatan/arah angin. Ini bisa menjadi sensor yang sangat penting yang saya lewatkan dalam model saya
- bereksperimen dengan sinar UV, gas dan sensor partikel
- tambahkan setidaknya dua stasiun di zona untuk data yang lebih baik (buat beberapa rata-rata yang lebih baik)
- kumpulkan beberapa tahun data lagi, saya telah bereksperimen dengan hanya setengah tahun
Beberapa perbaikan pemrosesan:
- coba untuk menyisipkan data dari sumber lain ke dalam model. Anda dapat mulai mengimpor data kecepatan angin dan menggabungkannya dengan data stasiun lokal untuk model yang lebih baik. Situs web ini menawarkan data historis: https://www.wunderground.com/history/
- optimalkan model Keras lebih baik dengan menyesuaikan: lapisan, jumlah neuron dalam lapisan, persentase dropout, fungsi metrik, fungsi optimizer, fungsi loss, ukuran batch, jumlah epoch pembelajaran
- coba arsitektur model lain, misalnya saya telah bereksperimen dengan LSTM (long short term memory) tetapi itu memberikan hasil sedikit lebih buruk)
Untuk mencoba parameter yang berbeda pada model pembelajaran Anda dapat menggunakan
python train.py --days_behind 600 --test-file-percent 10 --datapoints-behind 6 --hour-granularity 6 --grid-search
Ini akan mencari melalui nilai "batch_size", "epoch", "optimizer" dan "dropout" yang berbeda, mengevaluasi semua dan mencetak kombinasi terbaik untuk data Anda.
Jika Anda memiliki masukan pada pekerjaan saya silakan bagikan, terima kasih sudah tinggal sampai akhir tutorial!
Langkah 7: Bonus: Menggunakan Kumpulan Data Cuaca Resmi
Saya bertanya-tanya apakah saya bisa mendapatkan hasil yang lebih baik dengan stasiun cuaca yang lebih terpercaya, jadi saya mencari sedikit, dan saya menemukan "Darksky API" (https://darksky.net/dev), ini adalah alat yang bagus yang menyediakan data cuaca saat ini dan historis dengan lebih banyak data sensor:
- penglihatanJadi ini adalah data dari stasiun cuaca resmi, dan memiliki lebih banyak parameter saya pikir harus berjalan lebih baik jadi saya mencoba. Untuk mereplikasi temuan saya:
1.Unduh data dari darsky atau impor koleksi MongoDb saya:
a) Unduh
- untuk mengunduh sendiri, pertama buat akun di darsky dan dapatkan kunci API
- ganti kunci API di download_import/config.py
- juga dalam konfigurasi ganti koordinat geografis untuk lokasi yang ingin Anda prediksi hujan
- dalam konsol aktifkan lingkungan Anaconda "weather" dan jalankan:
python download_import/darksky.py -d 1000
- versi gratis API terbatas pada 1000 permintaan per hari jadi jika Anda ingin lebih banyak data Anda perlu menunggu lebih lama
b) Impor data yang saya unduh untuk kota Bucharest
- dalam konsol jalankan
mongoimport -d weather -c darksky --file sample_data/darksky.json
2. Saat Anda melatih model tentukan bahwa harus berjalan pada kumpulan data "darksy"
python train.py -d 2000 -p 20 -dp 4 -hg 6 --data-source darksky
3. Untuk melihat hasilnya jalankan skrip prediksi batch seperti sebelumnya
python predict_batch.py -f sample_data/test_data.csv
Anda akan melihat bahwa persentase prediksi keseluruhan telah naik dari sekitar 80% menjadi 90%. Juga akurasi prediksi saat hanya mempertimbangkan hari hujan telah naik.
Jadi ya, kumpulan data benar-benar penting.