Voici un petit exercice qui modélise avec un petit algorithme d'intelligence artificielle les chances de survie à la catastrophe du Titanic, en fonction de divers paramètres.
Je vous passe les détails techniques, le modèle est appelé Bayésien naïf, et on trouve d'excellentes explications sur Internet.
Pour l'exécuter, il vous faut un ESP32. Uploadez d'abord le fichier de données (voir tout en bas) dans le SPIFFS grâce à un plugin de l'IDE (au fait, est-ce qu'il est compatible de la v2 beta ?). Voir instructions ici :
Ensuite, installez la bibliothèque Naive Bayes, ici :
Il reste à téléverser le code suivant et à l'exécuter :
/*
Naive Bayes algorithm implementation for the
Titanic test case
(c) Lesept, September 2021
*/
#include <Arduino.h>
#include "FS.h"
#include "SPIFFS.h"
#include "NaiveBayes.h"
#define FORMAT_SPIFFS_IF_FAILED true
const char * path = "/Clean_Dataset.csv";
#define nData 707
#define nFeatures 4
#define nClasses 2
NB Titanic(nData, nFeatures, nClasses);
std::vector<Data>dataset;
int inputInt() {
String value;
while (Serial.available() == 0) {}
value = Serial.readString();
if (value.length() > 0) {
int n = value.toInt();
Serial.println(n);
return n;
}
return 0;
}
char inputChar() {
String value;
while (Serial.available() == 0) {}
value = Serial.readString();
if (value.length() > 0) {
value.toUpperCase();
char n = value.charAt(0);
Serial.println(n);
return n;
}
return 0;
}
void setup() {
char buffer[50];
Serial.begin(115200);
// Mount SPIFFS
if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) {
Serial.println("SPIFFS Mount Failed");
return;
}
// Open dataset file
File file = SPIFFS.open(path);
if (!file || file.isDirectory()) {
Serial.println("- failed to open file for reading");
return;
}
// Read file
Serial.printf("Reading data from file: %s\n", path);
int n = 0;
// Read a line
while (file.available()) {
int i = 0;
char c = file.read();
while (c != '\n') {
buffer[i++] = c;
c = file.read();
}
buffer[i] = NULL;
// Extract numbers from the line
if (n != 0) {
char * pch = strtok(buffer, ";");
int k = 0;
uint8_t y = 0;
std::vector<uint8_t> x;
while (pch != NULL)
{
if (k == 0) {
y = atoi(pch);
}
else {
int u;
if (k < 4) u = atoi(pch);
else {
u = atof(pch) / 2;
if (u > 255) u = 255;
}
x.push_back(u);
}
k++;
pch = strtok(NULL, ";");
}
// Add data to dataset
// Serial.printf ("%d -- %d %d %d %d --> survived %d\n", n, x[0], x[1], x[2], 2 * x[3], y);
x.push_back(y);
Titanic.addDataCat(x, dataset);
} else Serial.println(buffer);
n++;
}
file.close();
Serial.printf("Read %d data from file\n", n - 1);
// Fit the dataset
Titanic.fit(dataset);
int data[] = {2, 0, 5, 27};
data[3] /= 2;
if (data[3] > 255) data[3] = 255;
std::vector<uint8_t> x (data, data + 4);
uint8_t predict = Titanic.predictCatFit(x, dataset);
Serial.printf("Prediction %d\n", predict);
}
void loop() {
bool ok;
Serial.println ("\n _");
Serial.println (" / \\");
Serial.println (" __/ _ \\_ , , ,");
Serial.println (" /_ - \\ \\ ,: ,: ,: ");
Serial.println (" / / / \\ \\ __||_||_||_||___");
Serial.println (" | | _ / | ____[\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"]___");
Serial.println (" / / \\ \\ \\ @ ''''''''''''''''''''/");
Serial.println (" ~~^~^~~~^~^~^~~^~^~^~~~^~^~^^~^~^~^~^~^~^~^~~^~^~^~^~~^~^");
Serial.println ("Did you survive the TITANIC ? ");
ok = false;
int age;
while (!ok) {
Serial.println("Enter your age (2 to 70)");
age = inputInt();
if (age > 1 && age < 71) ok = true;
}
ok = false;
int sex;
while (!ok) {
Serial.println("Are you Male or Female (M or F) ? ");
char c = inputChar();
if (c == 'M' || c == 'F') ok = true;
sex = (c == 'M') ? 1 : 0;
}
ok = false;
int classe;
while (!ok) {
Serial.println("In which class did you travel (1, 2 or 3) ? ");
classe = inputInt();
if (classe > 0 && classe < 4) ok = true;
}
ok = false;
int fare;
while (!ok) {
Serial.println("What is the fare of your trip (2 to 510 £) ? ");
fare = inputInt();
if (fare > 1 && fare < 511) ok = true;
}
int data[] = {classe, sex, age, fare / 2};
std::vector<uint8_t> x (data, data + 4);
uint8_t predict = Titanic.predictCatFit(x, dataset);
for (int i = 0; i < 5 + random(15); i++) {
Serial.print(".");
delay(random(600));
}
Serial.printf((predict) ? "\nCongratulations, you survived !!!\n" : "\nSorry, you died...\n");
}
Bonne chance, et n'oubliez pas votre bouée de sauvetage...
Fichier de données : extrayez le fichier csv et mettez-le dans un répertoire data
Clean_Dataset.zip (2.6 KB)
Vous avez un répertoire Titanic, contenant :
- Titanic.ino
- data (répertoire dans lequel se trouve le fichier csv extrait de l'archive zip)