SlideShare une entreprise Scribd logo
1  sur  76
Télécharger pour lire hors ligne
@Miralak Lausanne JUG 23.03.2017
Exemple d’IOT et ML avec Android,
Cassandra et Spark
Amira Lakhal @miralak
1
@Miralak Lausanne JUG 23.03.20172
About me
Software Developer Java &
@Miralak
github.com/MiraLak
Running addict
@Miralak Lausanne JUG 23.03.2017
Duchess France
3
www.duchess-france.org
@DuchessFr
@Miralak Lausanne JUG 23.03.20174
Internet Of Things
@Miralak Lausanne JUG 23.03.20175
Internet of things (IOT)
@Miralak Lausanne JUG 23.03.20176
Internet of things (IOT)
@Miralak Lausanne JUG 23.03.20177
Big Data Era
Source: micronautomata.com
@Miralak Lausanne JUG 23.03.20178
Transformation de la Data
Data
Knowledge
Information
Wisdom
Understanding
Context
@Miralak Lausanne JUG 23.03.20179
IOT Future
Source: EX_MACHINA 2015
@Miralak Lausanne JUG 23.03.201710
La réalité
Source: Aldebaran
@Miralak Lausanne JUG 23.03.201711
Mes objets connectés
@Miralak Lausanne JUG 23.03.201712
Objectif
La reconnaissance de l’activité physique en se basant sur les données d’un
capteur: l’accéléromètre
Activitées:
● Marcher,
● Courir,
● Debout,
● Assis.
➔ Utilisation pour des suivis médicaux
@Miralak Lausanne JUG 23.03.201713
Acceleromètre
➔ Capteur de mouvement
➔ Mesure l’accélération
➔ Usages multiples
@Miralak Lausanne JUG 23.03.201714
Acceleromètre
Chaque accélération contient:
● un timestamp (eg, 1428773040488)
● la force d’accélération selon l’axe x (unité m/s²)
● la force d’accélération selon l’axe y (unité m/s²)
● la force d’accélération selon l’axe z (unité m/s²)
@Miralak Lausanne JUG 23.03.201715
Timeseries
@Miralak Lausanne JUG 23.03.201716
Application Android
https://github.com/MiraLak/AccelerometerAndroidApp
@Miralak Lausanne JUG 23.03.201717
Collecte des données
Serveur REST Base de données
https://github.com/MiraLak/accelerometer-rest-to-cassandra
@Miralak Lausanne JUG 23.03.201718
Stockage des données
@Miralak Lausanne JUG 23.03.201719
@Miralak Lausanne JUG 23.03.201720
Historique
● Créé par Facebook
● Open-source en 2008
● current version 3.10
● Orienté colonne ☞ table distribuée
@Miralak Lausanne JUG 23.03.201721
Caractéristiques
● Scalabilité linéaire
● Master-less: peer to peer
● Simplicité opérationnelle
● Multi-datacenter
● No SPOF ☞ Haute disponibilité (≈100% up-time)
@Miralak Lausanne JUG 23.03.201722
Last Write Win
INSERT INTO users(login, name, age) VALUES (‘DuchessFr’ , ‘Duchess France’, ‘5’);
DuchessFr
name(t1) age(t1)
Duchess France 5
auto-generated timestamp
@Miralak Lausanne JUG 23.03.201723
Last Write Win
UPDATE users SET age = ‘6’ WHERE login=‘DuchessFr’ ;
DuchessFr
name(t1) age(t1)
Duchess
France
5
DuchessFr
age(t2)
6
SSTable1 SSTable2
@Miralak Lausanne JUG 23.03.201724
Last Write Win
DELETE age from users WHERE login=‘DuchessFr’ ;
DuchessFr
name(t1) age(t1)
Duchess
France
5
SSTable1
DuchessFr
age(t2)
6
SSTable2
DuchessFr
age(t3)
X
SSTable3
@Miralak Lausanne JUG 23.03.201725
Last Write Win
SELECT age from users WHERE login=‘DuchessFr’ ;
DuchessFr
name(t1) age(t1)
Duchess
France
5
DuchessFr
age(t2)
6
SSTable2
DuchessFr
age(t3)
X
SSTable3SSTable1 SSTable3
@Miralak Lausanne JUG 23.03.201726
Compaction
DuchessFr
name(t1) age(t1)
Duchess
France
5
DuchessFr
age(t2)
6
SSTable2
DuchessFr
age(t3)
X
SSTable3SSTable1
SSTable4
DuchessFr
name(t1) age(t3)
Duchess
France
@Miralak Lausanne JUG 23.03.201727
Timeseries avec Cassandra
Nous allons utiliser des données historiques
➢ Timeseries data model
L’utilisateur et le timestamp sont uniques
➢ Sauvegarder autant que nécessaire
@Miralak Lausanne JUG 23.03.201728
Timeseries data model
CREATE TABLE accelerometer (
user_id text,
timestamp bigint,
x double, y double, z double,
PRIMARY KEY (( user_id ),timestamp)
);
Clustering column
Partition key
@Miralak Lausanne JUG 23.03.201729
Vue logique
user-id timestamp x y z
TEST_USER 1447034733210 10.9 34.5 12.6
TEST_USER 1447034733344 15.4 39.9 16.3
TEST_USER 1447034733462 13.5 36.1 20.3
TEST_USER 1447034733556 13.0 41.3 22.8”
@Miralak Lausanne JUG 23.03.201730
Vue sur disque
TEST_USER
1447034733210 1447034733344 1447034733462
x Y Z x y z x y z
10.9 34.5 12.6 15.4 39.9 16.3 13.5 36.1 20.3
@Miralak Lausanne JUG 23.03.201731
Timeseries data model
CREATE TABLE accelerometer (
user_id text,
date text,
timestamp bigint,
x double, y double, z double,
PRIMARY KEY ((user_id, date),timestamp)
);
@Miralak Lausanne JUG 23.03.201732
Vue logique
user-id:date timestamp x y z
TEST_USER:
24-09-2015
1446034733566
10.9 34.5 12.6
TEST_USER:
24-09-2015
1446034733631 15.4 39.9 16.3
TEST_USER:
24-09-2015
1446034733740 13.5 36.1 20.3
TEST_USER:
24-09-2015
1446034733830 13.0 41.3 22.8
@Miralak Lausanne JUG 23.03.201733
Vue sur disque
TEST_USER
:24-09-2015
1446034733566 1446034733631 .. 1446034734120
x Y Z x y z .. x y z
10.9 34.5 12.6 15.4 39.9 16.3 .. 13.5 36.1 20.3
TEST_USER
:25-09-2015
1447034733210 1447034733300 .. 1447034733810
x Y Z x y z .. x y z
13.3 30.5, 12.1 25.2 34.9 16.1 .. 15.0 32.1 12.4
@Miralak Lausanne JUG 23.03.201734
Requêtage
Range queries ☞ Slice on disk
Select user_id, date, timestamp, x, y, z
From accelerometer
Where user_id =”TEST_USER”
and date = “24-04-2015”
and timestamp > “1447034733462” and timestamp < “1447034733890”
@Miralak Lausanne JUG 23.03.201735
Ordre d’aggrégation
CREATE TABLE latest_accelerations (
user_id text,
timestamp bigint,
x double, y double, z double,
PRIMARY KEY (user_id, timestamp)
WITH CLUSTERING ORDER BY (timestamp, DESC);
);
@Miralak Lausanne JUG 23.03.201736
Expiration: TTL
INSERT INTO latest_accelerations( user_id, timestamp, x, y, z )
VALUES ( ’TEST_USER’, 1447034733462, 10.9, 34.5, 12.6 )
USING TTL 20;
@Miralak Lausanne JUG 23.03.201737
Analyse des données
@Miralak Lausanne JUG 23.03.201738
@Miralak Lausanne JUG 23.03.201739
Historique
● Créé par AMPLab
● Open-source en 2010
● Version actuelle 2.1.0
● Totalement écrit en Scala
● Calcul distribué en mémoire vive
@Miralak Lausanne JUG 23.03.201740
Ecosystème
Spark Core
Spark SQL
Spark
Streaming
ML lib GraphX
@Miralak Lausanne JUG 23.03.201741
Data sources
Source: Databricks
@Miralak Lausanne JUG 23.03.201742
RDD
● Abstraction : collection d’objet
● Opéré en parallèle
● Tolérant aux fautes sans réplication
@Miralak Lausanne JUG 23.03.2017
Transformations et actions
@Miralak Lausanne JUG 23.03.2017
SparkConf conf = new SparkConf()
.setAppName("Wordcount")
.setMaster("local[*]");
JavaSparkContext sc = new JavaSparkContext(conf);
//Transformations
JavaRDD<String> words = sc.textFile(myFilePath)
.flatMap(line -> Arrays.asList(line.split(" ")));
JavaPairRDD<String, Integer> pairs = words.mapToPair(x -> new Tuple2(x,1))
.reduceByKey((a,b) -> a+b)
.filter(tuple -> tuple._2() > 3);
//Action
List<Tuple2<String, Integer>> result = words.collect();
44
Exemple: Word count
@Miralak Lausanne JUG 23.03.201745
Gestionnaire de cluster
● Standalone
● Mesos
● Yarn
Source: http://spark.apache.org
@Miralak Lausanne JUG 23.03.201746
Caractéristiques de Spark
● Rapide
● Flexible
● Facile à utiliser
@Miralak Lausanne JUG 23.03.201747
Analyse en temps réel
@Miralak Lausanne JUG 23.03.201748
&
@Miralak Lausanne JUG 23.03.201749
Spark Cassandra Connector
● Open source
● Version 2.0
● Ecrit en Scala
● Charge les données de Cassandra vers Spark
● Ecrit les données de Spark vers Cassandra
https://github.com/datastax/spark-cassandra-connector
@Miralak Lausanne JUG 23.03.201750
Spark Cassandra Connector
Exposes les tables Cassandra comme des Spark RDD + Spark DStreams
c*
Cassandra
driver
Spark
Cassandra
Connector
Spark
@Miralak Lausanne JUG 23.03.2017
Setup Spark Connection
val sparkConf:SparkConf = new SparkConf()
.setAppName("activityRecognition")
.set("spark.cassandra.connection.host", "127.0.0.1"))
.set("spark.cassandra.connection.native.port", "9142")
.setMaster("local[*]");
val sc:SparkContext = new SparkContext(sparkConf);
51
@Miralak Lausanne JUG 23.03.2017
De Cassandra vers Spark
val cassandraRowsRDD:CassandraRDD[CassandraRow] =
new SparkContextFunctions(sc)
.cassandraTable("activityrecognition", "training");
val users:Array[String] = cassandraRowsRDD.select("user_id")
.distinct
.map(row => row.toMap)
.map(entry => entry.get("user_id"))
.collect();
52
@Miralak Lausanne JUG 23.03.2017
Spark Streaming
Scalable, high-throughput, fault-tolerant stream processing
53
@Miralak Lausanne JUG 23.03.2017
Spark Streaming
// declare a streaming context
val ssc = new StreamingContext(sparkConf, Durations.seconds(2))
val cassandraReceiver: ReceiverInputDStream[RDD[CassandraRow]] =
ssc.receiverStream(
new CassandraReceiver(StorageLevel.MEMORY_ONLY)) // custom Cassandra receiver
// The transformations are done here then print the receiver value
cassandraReceiver.map(rdd => computePrediction(model, rdd)).print(0)
ssc.start
ssc.awaitTermination // Wait for the computation to terminate
54
@Miralak Lausanne JUG 23.03.2017
Spark Streaming
class CassandraReceiver(storage: StorageLevel) extends
Receiver[RDD[CassandraRow]](storage: StorageLevel) with Logging{
override def onStart() = { // Start the thread that receives data over a connection
new Thread() {
override def run() = {
receive() //Read data from Cassandra
}
}.start()
}
override def onStop() = { //Nothing to do }
}
55
@Miralak Lausanne JUG 23.03.2017
Et la prédiction?
56
@Miralak Lausanne JUG 23.03.2017
Reconnaissance d’activité
Activités possibles: marcher, courir, debout ou assis
Mesures depuis un acceleromètre : timeseries
Classification d’un timeserie en des
classes d’activités physiques
Machine Learning
57
@Miralak Lausanne JUG 23.03.2017
Classification multiclasses
Labélisé un pattern inconnu à partir de patterns connus
Régression logistique Naive Bayes Random forest
58
@Miralak Lausanne JUG 23.03.2017
Random forest model
59
@Miralak Lausanne JUG 23.03.2017
Apprentissage supervisé
features label
features label
features label
features label
Features Label
Features ?
Train
Predict
60
@Miralak Lausanne JUG 23.03.2017
Modèle prédictif
● Collecter les données labélisées
● Identifier les caractéristiques (features)
● Calculer les caractérisques
● Créer le modèle Random Forest et l’entrainer
● Prédire l’activité
61
@Miralak Lausanne JUG 23.03.2017
Echantillon
62
@Miralak Lausanne JUG 23.03.2017
Collecte des données
63
@Miralak Lausanne JUG 23.03.2017
Application Android
64
@Miralak Lausanne JUG 23.03.2017
Données d’entraînement
65
@Miralak Lausanne JUG 23.03.2017
Données d’entraînement
13679 training acceleration => Seulement 1.6 Mo
66
@Miralak Lausanne JUG 23.03.2017
Echantillonnage
67
@Miralak Lausanne JUG 23.03.2017
Identification des caractéristiques
Calculer la différence X < Y ou X > Y
68
@Miralak Lausanne JUG 23.03.2017
Identification des caractéristiques
Calculer l’amplitude entre les pics de Y
69
@Miralak Lausanne JUG 23.03.2017
Caractéristiques
● Accélération moyenne pour chaque axe
● La différence moyenne entre l’axe X et l’axe Y
● La variance (pour chaque axe)
● L’écart type (pour chaque axe) 1/n * ∑ (x - mean_x)
● La difference absolue moyenne (pour chaque axe)
● Le résultant moyen d’accélération 1/n * ∑ √(x² + y² + z²)
● L'amplitude moyenne pour l’axe des Y
70
@Miralak Lausanne JUG 23.03.2017
Calcul des caractéristiques
//Data comes from ReceiverStream
val accelerationData: RDD[Array[Double]] = data.map(row => row.toMap)
.map(row => Array(row.getOrElse("x",0), row.getOrElse("y",0) ,row.getOrElse("z",0))
.map(row => row.map(_.doubleValue()))
val vectorsXYZ: RDD[Vector] = accelerationData.map(Vectors.dense)
var summary: MultivariateStatisticalSummary = Statistics.colStats(data)
val mean: Array[Double] = summary.mean.toArray
val variance: Array[Double] = summary.variance.toArray
val difference: Double = feature.computeDifferenceBetweenAxes(mean)
//build LabeledPoint with an activity label
val labeledPoint:LabeledPoint = new LabeledPoint(label, Vectors.dense(features))
71
@Miralak Lausanne JUG 23.03.2017
Random Forest Model
// parameters
val categoricalFeaturesInfo: Map[Int, Int] = Map.empty
val numTree: Int = 10
val numClasses: Int = 4
val featureSubsetStrategy: String = "auto"//nb features for splits at each node
val impurity: String = "gini"
val maxDepth: Int = 20
val maxBins: Int = 32
val randomSeeds: Int = 12345 //Random seed for bootstrapping and choosing subsets
// create model
val model = RandomForest.trainClassifier(trainingData, numClasses,
categoricalFeaturesInfo, numTree, featureSubsetStrategy, impurity, maxDepth,
maxBins, randomSeeds)
model.save(sc, "randomForestModel")
72
@Miralak Lausanne JUG 23.03.2017
Précision
● 1.6 Mo mesures d’accélération
● 15 caractéristiques calculées
Random forest accuracy 92.3%
73
@Miralak Lausanne JUG 23.03.2017
Live Demo
74
@Miralak Lausanne JUG 23.03.2017
Conclusion
● Collecter les données depuis un objet et l’analyser
● Les capteurs combinés?
● Une infinité de possibilité avec l’IOT
@Miralak Lausanne JUG 23.03.2017
Merci
76
@Miralak
github.com/MiraLak

Contenu connexe

Plus de JUG Lausanne

OpenDS - Ludovic Poitou - December 2010
OpenDS - Ludovic Poitou - December 2010OpenDS - Ludovic Poitou - December 2010
OpenDS - Ludovic Poitou - December 2010JUG Lausanne
 
Spring Batch - Julien Jakubowski - November 2010
Spring Batch - Julien Jakubowski - November 2010Spring Batch - Julien Jakubowski - November 2010
Spring Batch - Julien Jakubowski - November 2010JUG Lausanne
 
Infinispan - Galder Zamarreno - October 2010
Infinispan - Galder Zamarreno - October 2010Infinispan - Galder Zamarreno - October 2010
Infinispan - Galder Zamarreno - October 2010JUG Lausanne
 
No Sql - Olivier Mallassi - September 2010
No Sql - Olivier Mallassi - September 2010No Sql - Olivier Mallassi - September 2010
No Sql - Olivier Mallassi - September 2010JUG Lausanne
 
Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010
Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010
Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010JUG Lausanne
 
Introduction à Scala - Michel Schinz - January 2010
Introduction à Scala - Michel Schinz - January 2010Introduction à Scala - Michel Schinz - January 2010
Introduction à Scala - Michel Schinz - January 2010JUG Lausanne
 
Introduction Groovy / Grails - Cyril Picat - December 2009
Introduction Groovy / Grails - Cyril Picat - December 2009Introduction Groovy / Grails - Cyril Picat - December 2009
Introduction Groovy / Grails - Cyril Picat - December 2009JUG Lausanne
 
Initiation aux tests fonctionnels - Philippe Kernevez - October 2009
Initiation aux tests fonctionnels - Philippe Kernevez - October 2009Initiation aux tests fonctionnels - Philippe Kernevez - October 2009
Initiation aux tests fonctionnels - Philippe Kernevez - October 2009JUG Lausanne
 
Sonar - Freddy Mallet - April 2009
Sonar - Freddy Mallet - April 2009Sonar - Freddy Mallet - April 2009
Sonar - Freddy Mallet - April 2009JUG Lausanne
 
Maven2 - Philippe Kernevez - March 2009
Maven2 - Philippe Kernevez - March 2009Maven2 - Philippe Kernevez - March 2009
Maven2 - Philippe Kernevez - March 2009JUG Lausanne
 
Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009
Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009
Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009JUG Lausanne
 
XML & Java - Raphaël Tagliani - March 2008
XML & Java - Raphaël Tagliani - March 2008XML & Java - Raphaël Tagliani - March 2008
XML & Java - Raphaël Tagliani - March 2008JUG Lausanne
 
Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008
Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008
Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008JUG Lausanne
 
Scripting with Java FX - Cédric Tabin - December 2007
Scripting with Java FX - Cédric Tabin - December 2007Scripting with Java FX - Cédric Tabin - December 2007
Scripting with Java FX - Cédric Tabin - December 2007JUG Lausanne
 
GlassFish Update and Directions - Karim Mazouni - November 2007
GlassFish Update and Directions - Karim Mazouni - November 2007GlassFish Update and Directions - Karim Mazouni - November 2007
GlassFish Update and Directions - Karim Mazouni - November 2007JUG Lausanne
 
JUG Launch - Cédric Tabin - September 2007
JUG Launch - Cédric Tabin - September 2007JUG Launch - Cédric Tabin - September 2007
JUG Launch - Cédric Tabin - September 2007JUG Lausanne
 
NetBeans 5.5 and Java EE - Cédric Tabin - June 2007
NetBeans 5.5 and Java EE - Cédric Tabin - June 2007NetBeans 5.5 and Java EE - Cédric Tabin - June 2007
NetBeans 5.5 and Java EE - Cédric Tabin - June 2007JUG Lausanne
 

Plus de JUG Lausanne (17)

OpenDS - Ludovic Poitou - December 2010
OpenDS - Ludovic Poitou - December 2010OpenDS - Ludovic Poitou - December 2010
OpenDS - Ludovic Poitou - December 2010
 
Spring Batch - Julien Jakubowski - November 2010
Spring Batch - Julien Jakubowski - November 2010Spring Batch - Julien Jakubowski - November 2010
Spring Batch - Julien Jakubowski - November 2010
 
Infinispan - Galder Zamarreno - October 2010
Infinispan - Galder Zamarreno - October 2010Infinispan - Galder Zamarreno - October 2010
Infinispan - Galder Zamarreno - October 2010
 
No Sql - Olivier Mallassi - September 2010
No Sql - Olivier Mallassi - September 2010No Sql - Olivier Mallassi - September 2010
No Sql - Olivier Mallassi - September 2010
 
Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010
Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010
Java EE 6 & GlassFish V3 - Alexis Moussine-Pouchkine - May 2010
 
Introduction à Scala - Michel Schinz - January 2010
Introduction à Scala - Michel Schinz - January 2010Introduction à Scala - Michel Schinz - January 2010
Introduction à Scala - Michel Schinz - January 2010
 
Introduction Groovy / Grails - Cyril Picat - December 2009
Introduction Groovy / Grails - Cyril Picat - December 2009Introduction Groovy / Grails - Cyril Picat - December 2009
Introduction Groovy / Grails - Cyril Picat - December 2009
 
Initiation aux tests fonctionnels - Philippe Kernevez - October 2009
Initiation aux tests fonctionnels - Philippe Kernevez - October 2009Initiation aux tests fonctionnels - Philippe Kernevez - October 2009
Initiation aux tests fonctionnels - Philippe Kernevez - October 2009
 
Sonar - Freddy Mallet - April 2009
Sonar - Freddy Mallet - April 2009Sonar - Freddy Mallet - April 2009
Sonar - Freddy Mallet - April 2009
 
Maven2 - Philippe Kernevez - March 2009
Maven2 - Philippe Kernevez - March 2009Maven2 - Philippe Kernevez - March 2009
Maven2 - Philippe Kernevez - March 2009
 
Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009
Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009
Introduction à Google Web Toolkit (GWT) - Philippe Kernevez - February 2009
 
XML & Java - Raphaël Tagliani - March 2008
XML & Java - Raphaël Tagliani - March 2008XML & Java - Raphaël Tagliani - March 2008
XML & Java - Raphaël Tagliani - March 2008
 
Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008
Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008
Visual Mobile Applications with Netbeans 6.0 - Cédric Tabin - February 2008
 
Scripting with Java FX - Cédric Tabin - December 2007
Scripting with Java FX - Cédric Tabin - December 2007Scripting with Java FX - Cédric Tabin - December 2007
Scripting with Java FX - Cédric Tabin - December 2007
 
GlassFish Update and Directions - Karim Mazouni - November 2007
GlassFish Update and Directions - Karim Mazouni - November 2007GlassFish Update and Directions - Karim Mazouni - November 2007
GlassFish Update and Directions - Karim Mazouni - November 2007
 
JUG Launch - Cédric Tabin - September 2007
JUG Launch - Cédric Tabin - September 2007JUG Launch - Cédric Tabin - September 2007
JUG Launch - Cédric Tabin - September 2007
 
NetBeans 5.5 and Java EE - Cédric Tabin - June 2007
NetBeans 5.5 and Java EE - Cédric Tabin - June 2007NetBeans 5.5 and Java EE - Cédric Tabin - June 2007
NetBeans 5.5 and Java EE - Cédric Tabin - June 2007
 

Exemple d'IOT et ML avec Android, Cassandra et Spark

  • 1. @Miralak Lausanne JUG 23.03.2017 Exemple d’IOT et ML avec Android, Cassandra et Spark Amira Lakhal @miralak 1
  • 2. @Miralak Lausanne JUG 23.03.20172 About me Software Developer Java & @Miralak github.com/MiraLak Running addict
  • 3. @Miralak Lausanne JUG 23.03.2017 Duchess France 3 www.duchess-france.org @DuchessFr
  • 4. @Miralak Lausanne JUG 23.03.20174 Internet Of Things
  • 5. @Miralak Lausanne JUG 23.03.20175 Internet of things (IOT)
  • 6. @Miralak Lausanne JUG 23.03.20176 Internet of things (IOT)
  • 7. @Miralak Lausanne JUG 23.03.20177 Big Data Era Source: micronautomata.com
  • 8. @Miralak Lausanne JUG 23.03.20178 Transformation de la Data Data Knowledge Information Wisdom Understanding Context
  • 9. @Miralak Lausanne JUG 23.03.20179 IOT Future Source: EX_MACHINA 2015
  • 10. @Miralak Lausanne JUG 23.03.201710 La réalité Source: Aldebaran
  • 11. @Miralak Lausanne JUG 23.03.201711 Mes objets connectés
  • 12. @Miralak Lausanne JUG 23.03.201712 Objectif La reconnaissance de l’activité physique en se basant sur les données d’un capteur: l’accéléromètre Activitées: ● Marcher, ● Courir, ● Debout, ● Assis. ➔ Utilisation pour des suivis médicaux
  • 13. @Miralak Lausanne JUG 23.03.201713 Acceleromètre ➔ Capteur de mouvement ➔ Mesure l’accélération ➔ Usages multiples
  • 14. @Miralak Lausanne JUG 23.03.201714 Acceleromètre Chaque accélération contient: ● un timestamp (eg, 1428773040488) ● la force d’accélération selon l’axe x (unité m/s²) ● la force d’accélération selon l’axe y (unité m/s²) ● la force d’accélération selon l’axe z (unité m/s²)
  • 15. @Miralak Lausanne JUG 23.03.201715 Timeseries
  • 16. @Miralak Lausanne JUG 23.03.201716 Application Android https://github.com/MiraLak/AccelerometerAndroidApp
  • 17. @Miralak Lausanne JUG 23.03.201717 Collecte des données Serveur REST Base de données https://github.com/MiraLak/accelerometer-rest-to-cassandra
  • 18. @Miralak Lausanne JUG 23.03.201718 Stockage des données
  • 19. @Miralak Lausanne JUG 23.03.201719
  • 20. @Miralak Lausanne JUG 23.03.201720 Historique ● Créé par Facebook ● Open-source en 2008 ● current version 3.10 ● Orienté colonne ☞ table distribuée
  • 21. @Miralak Lausanne JUG 23.03.201721 Caractéristiques ● Scalabilité linéaire ● Master-less: peer to peer ● Simplicité opérationnelle ● Multi-datacenter ● No SPOF ☞ Haute disponibilité (≈100% up-time)
  • 22. @Miralak Lausanne JUG 23.03.201722 Last Write Win INSERT INTO users(login, name, age) VALUES (‘DuchessFr’ , ‘Duchess France’, ‘5’); DuchessFr name(t1) age(t1) Duchess France 5 auto-generated timestamp
  • 23. @Miralak Lausanne JUG 23.03.201723 Last Write Win UPDATE users SET age = ‘6’ WHERE login=‘DuchessFr’ ; DuchessFr name(t1) age(t1) Duchess France 5 DuchessFr age(t2) 6 SSTable1 SSTable2
  • 24. @Miralak Lausanne JUG 23.03.201724 Last Write Win DELETE age from users WHERE login=‘DuchessFr’ ; DuchessFr name(t1) age(t1) Duchess France 5 SSTable1 DuchessFr age(t2) 6 SSTable2 DuchessFr age(t3) X SSTable3
  • 25. @Miralak Lausanne JUG 23.03.201725 Last Write Win SELECT age from users WHERE login=‘DuchessFr’ ; DuchessFr name(t1) age(t1) Duchess France 5 DuchessFr age(t2) 6 SSTable2 DuchessFr age(t3) X SSTable3SSTable1 SSTable3
  • 26. @Miralak Lausanne JUG 23.03.201726 Compaction DuchessFr name(t1) age(t1) Duchess France 5 DuchessFr age(t2) 6 SSTable2 DuchessFr age(t3) X SSTable3SSTable1 SSTable4 DuchessFr name(t1) age(t3) Duchess France
  • 27. @Miralak Lausanne JUG 23.03.201727 Timeseries avec Cassandra Nous allons utiliser des données historiques ➢ Timeseries data model L’utilisateur et le timestamp sont uniques ➢ Sauvegarder autant que nécessaire
  • 28. @Miralak Lausanne JUG 23.03.201728 Timeseries data model CREATE TABLE accelerometer ( user_id text, timestamp bigint, x double, y double, z double, PRIMARY KEY (( user_id ),timestamp) ); Clustering column Partition key
  • 29. @Miralak Lausanne JUG 23.03.201729 Vue logique user-id timestamp x y z TEST_USER 1447034733210 10.9 34.5 12.6 TEST_USER 1447034733344 15.4 39.9 16.3 TEST_USER 1447034733462 13.5 36.1 20.3 TEST_USER 1447034733556 13.0 41.3 22.8”
  • 30. @Miralak Lausanne JUG 23.03.201730 Vue sur disque TEST_USER 1447034733210 1447034733344 1447034733462 x Y Z x y z x y z 10.9 34.5 12.6 15.4 39.9 16.3 13.5 36.1 20.3
  • 31. @Miralak Lausanne JUG 23.03.201731 Timeseries data model CREATE TABLE accelerometer ( user_id text, date text, timestamp bigint, x double, y double, z double, PRIMARY KEY ((user_id, date),timestamp) );
  • 32. @Miralak Lausanne JUG 23.03.201732 Vue logique user-id:date timestamp x y z TEST_USER: 24-09-2015 1446034733566 10.9 34.5 12.6 TEST_USER: 24-09-2015 1446034733631 15.4 39.9 16.3 TEST_USER: 24-09-2015 1446034733740 13.5 36.1 20.3 TEST_USER: 24-09-2015 1446034733830 13.0 41.3 22.8
  • 33. @Miralak Lausanne JUG 23.03.201733 Vue sur disque TEST_USER :24-09-2015 1446034733566 1446034733631 .. 1446034734120 x Y Z x y z .. x y z 10.9 34.5 12.6 15.4 39.9 16.3 .. 13.5 36.1 20.3 TEST_USER :25-09-2015 1447034733210 1447034733300 .. 1447034733810 x Y Z x y z .. x y z 13.3 30.5, 12.1 25.2 34.9 16.1 .. 15.0 32.1 12.4
  • 34. @Miralak Lausanne JUG 23.03.201734 Requêtage Range queries ☞ Slice on disk Select user_id, date, timestamp, x, y, z From accelerometer Where user_id =”TEST_USER” and date = “24-04-2015” and timestamp > “1447034733462” and timestamp < “1447034733890”
  • 35. @Miralak Lausanne JUG 23.03.201735 Ordre d’aggrégation CREATE TABLE latest_accelerations ( user_id text, timestamp bigint, x double, y double, z double, PRIMARY KEY (user_id, timestamp) WITH CLUSTERING ORDER BY (timestamp, DESC); );
  • 36. @Miralak Lausanne JUG 23.03.201736 Expiration: TTL INSERT INTO latest_accelerations( user_id, timestamp, x, y, z ) VALUES ( ’TEST_USER’, 1447034733462, 10.9, 34.5, 12.6 ) USING TTL 20;
  • 37. @Miralak Lausanne JUG 23.03.201737 Analyse des données
  • 38. @Miralak Lausanne JUG 23.03.201738
  • 39. @Miralak Lausanne JUG 23.03.201739 Historique ● Créé par AMPLab ● Open-source en 2010 ● Version actuelle 2.1.0 ● Totalement écrit en Scala ● Calcul distribué en mémoire vive
  • 40. @Miralak Lausanne JUG 23.03.201740 Ecosystème Spark Core Spark SQL Spark Streaming ML lib GraphX
  • 41. @Miralak Lausanne JUG 23.03.201741 Data sources Source: Databricks
  • 42. @Miralak Lausanne JUG 23.03.201742 RDD ● Abstraction : collection d’objet ● Opéré en parallèle ● Tolérant aux fautes sans réplication
  • 43. @Miralak Lausanne JUG 23.03.2017 Transformations et actions
  • 44. @Miralak Lausanne JUG 23.03.2017 SparkConf conf = new SparkConf() .setAppName("Wordcount") .setMaster("local[*]"); JavaSparkContext sc = new JavaSparkContext(conf); //Transformations JavaRDD<String> words = sc.textFile(myFilePath) .flatMap(line -> Arrays.asList(line.split(" "))); JavaPairRDD<String, Integer> pairs = words.mapToPair(x -> new Tuple2(x,1)) .reduceByKey((a,b) -> a+b) .filter(tuple -> tuple._2() > 3); //Action List<Tuple2<String, Integer>> result = words.collect(); 44 Exemple: Word count
  • 45. @Miralak Lausanne JUG 23.03.201745 Gestionnaire de cluster ● Standalone ● Mesos ● Yarn Source: http://spark.apache.org
  • 46. @Miralak Lausanne JUG 23.03.201746 Caractéristiques de Spark ● Rapide ● Flexible ● Facile à utiliser
  • 47. @Miralak Lausanne JUG 23.03.201747 Analyse en temps réel
  • 48. @Miralak Lausanne JUG 23.03.201748 &
  • 49. @Miralak Lausanne JUG 23.03.201749 Spark Cassandra Connector ● Open source ● Version 2.0 ● Ecrit en Scala ● Charge les données de Cassandra vers Spark ● Ecrit les données de Spark vers Cassandra https://github.com/datastax/spark-cassandra-connector
  • 50. @Miralak Lausanne JUG 23.03.201750 Spark Cassandra Connector Exposes les tables Cassandra comme des Spark RDD + Spark DStreams c* Cassandra driver Spark Cassandra Connector Spark
  • 51. @Miralak Lausanne JUG 23.03.2017 Setup Spark Connection val sparkConf:SparkConf = new SparkConf() .setAppName("activityRecognition") .set("spark.cassandra.connection.host", "127.0.0.1")) .set("spark.cassandra.connection.native.port", "9142") .setMaster("local[*]"); val sc:SparkContext = new SparkContext(sparkConf); 51
  • 52. @Miralak Lausanne JUG 23.03.2017 De Cassandra vers Spark val cassandraRowsRDD:CassandraRDD[CassandraRow] = new SparkContextFunctions(sc) .cassandraTable("activityrecognition", "training"); val users:Array[String] = cassandraRowsRDD.select("user_id") .distinct .map(row => row.toMap) .map(entry => entry.get("user_id")) .collect(); 52
  • 53. @Miralak Lausanne JUG 23.03.2017 Spark Streaming Scalable, high-throughput, fault-tolerant stream processing 53
  • 54. @Miralak Lausanne JUG 23.03.2017 Spark Streaming // declare a streaming context val ssc = new StreamingContext(sparkConf, Durations.seconds(2)) val cassandraReceiver: ReceiverInputDStream[RDD[CassandraRow]] = ssc.receiverStream( new CassandraReceiver(StorageLevel.MEMORY_ONLY)) // custom Cassandra receiver // The transformations are done here then print the receiver value cassandraReceiver.map(rdd => computePrediction(model, rdd)).print(0) ssc.start ssc.awaitTermination // Wait for the computation to terminate 54
  • 55. @Miralak Lausanne JUG 23.03.2017 Spark Streaming class CassandraReceiver(storage: StorageLevel) extends Receiver[RDD[CassandraRow]](storage: StorageLevel) with Logging{ override def onStart() = { // Start the thread that receives data over a connection new Thread() { override def run() = { receive() //Read data from Cassandra } }.start() } override def onStop() = { //Nothing to do } } 55
  • 56. @Miralak Lausanne JUG 23.03.2017 Et la prédiction? 56
  • 57. @Miralak Lausanne JUG 23.03.2017 Reconnaissance d’activité Activités possibles: marcher, courir, debout ou assis Mesures depuis un acceleromètre : timeseries Classification d’un timeserie en des classes d’activités physiques Machine Learning 57
  • 58. @Miralak Lausanne JUG 23.03.2017 Classification multiclasses Labélisé un pattern inconnu à partir de patterns connus Régression logistique Naive Bayes Random forest 58
  • 59. @Miralak Lausanne JUG 23.03.2017 Random forest model 59
  • 60. @Miralak Lausanne JUG 23.03.2017 Apprentissage supervisé features label features label features label features label Features Label Features ? Train Predict 60
  • 61. @Miralak Lausanne JUG 23.03.2017 Modèle prédictif ● Collecter les données labélisées ● Identifier les caractéristiques (features) ● Calculer les caractérisques ● Créer le modèle Random Forest et l’entrainer ● Prédire l’activité 61
  • 62. @Miralak Lausanne JUG 23.03.2017 Echantillon 62
  • 63. @Miralak Lausanne JUG 23.03.2017 Collecte des données 63
  • 64. @Miralak Lausanne JUG 23.03.2017 Application Android 64
  • 65. @Miralak Lausanne JUG 23.03.2017 Données d’entraînement 65
  • 66. @Miralak Lausanne JUG 23.03.2017 Données d’entraînement 13679 training acceleration => Seulement 1.6 Mo 66
  • 67. @Miralak Lausanne JUG 23.03.2017 Echantillonnage 67
  • 68. @Miralak Lausanne JUG 23.03.2017 Identification des caractéristiques Calculer la différence X < Y ou X > Y 68
  • 69. @Miralak Lausanne JUG 23.03.2017 Identification des caractéristiques Calculer l’amplitude entre les pics de Y 69
  • 70. @Miralak Lausanne JUG 23.03.2017 Caractéristiques ● Accélération moyenne pour chaque axe ● La différence moyenne entre l’axe X et l’axe Y ● La variance (pour chaque axe) ● L’écart type (pour chaque axe) 1/n * ∑ (x - mean_x) ● La difference absolue moyenne (pour chaque axe) ● Le résultant moyen d’accélération 1/n * ∑ √(x² + y² + z²) ● L'amplitude moyenne pour l’axe des Y 70
  • 71. @Miralak Lausanne JUG 23.03.2017 Calcul des caractéristiques //Data comes from ReceiverStream val accelerationData: RDD[Array[Double]] = data.map(row => row.toMap) .map(row => Array(row.getOrElse("x",0), row.getOrElse("y",0) ,row.getOrElse("z",0)) .map(row => row.map(_.doubleValue())) val vectorsXYZ: RDD[Vector] = accelerationData.map(Vectors.dense) var summary: MultivariateStatisticalSummary = Statistics.colStats(data) val mean: Array[Double] = summary.mean.toArray val variance: Array[Double] = summary.variance.toArray val difference: Double = feature.computeDifferenceBetweenAxes(mean) //build LabeledPoint with an activity label val labeledPoint:LabeledPoint = new LabeledPoint(label, Vectors.dense(features)) 71
  • 72. @Miralak Lausanne JUG 23.03.2017 Random Forest Model // parameters val categoricalFeaturesInfo: Map[Int, Int] = Map.empty val numTree: Int = 10 val numClasses: Int = 4 val featureSubsetStrategy: String = "auto"//nb features for splits at each node val impurity: String = "gini" val maxDepth: Int = 20 val maxBins: Int = 32 val randomSeeds: Int = 12345 //Random seed for bootstrapping and choosing subsets // create model val model = RandomForest.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo, numTree, featureSubsetStrategy, impurity, maxDepth, maxBins, randomSeeds) model.save(sc, "randomForestModel") 72
  • 73. @Miralak Lausanne JUG 23.03.2017 Précision ● 1.6 Mo mesures d’accélération ● 15 caractéristiques calculées Random forest accuracy 92.3% 73
  • 74. @Miralak Lausanne JUG 23.03.2017 Live Demo 74
  • 75. @Miralak Lausanne JUG 23.03.2017 Conclusion ● Collecter les données depuis un objet et l’analyser ● Les capteurs combinés? ● Une infinité de possibilité avec l’IOT
  • 76. @Miralak Lausanne JUG 23.03.2017 Merci 76 @Miralak github.com/MiraLak