SlideShare a Scribd company logo
Tools for Making
Machine Learning
more Reactive
Jeff Smith
@jeffksmithjr
jeffsmith.tech
Reactive Machine Learning
Background Survey
Reactive Systems
Reactive Strategies
Machine Learning Systems
Reactive Machine Learning
Reactive at Intent Media
Language Survey
Languages
● Scala
● Erlang/Elixir
● Python
Responding
Agriculture
Akka
● Scala & Java
● Actor model
● Concurrency
● Distribution
● Supervision
Model Microservices
Model Microservice in Akka HTTP
case class Prediction(id: Long, timestamp: Long, value: Double)
trait Protocols extends DefaultJsonProtocol {
implicit val predictionFormat = jsonFormat3(Prediction)
}
Model Microservice in Akka HTTP
def model(features: Map[Char, Double]) = {
val coefficients = ('a' to 'z').zip(1 to 26).toMap
val predictionValue = features.map {
case (identifier, value) =>
coefficients.getOrElse(identifier, 0) * value
}.sum / features.size
Prediction(Random.nextLong(), System.currentTimeMillis(), predictionValue)
}
def parseFeatures(features: String): Map[String, Double] = {
features.parseJson.convertTo[Map[Char, Double]]
}
def predict(features: String): Prediction = {
model(parseFeatures(features))
}
Model Microservice in Akka HTTP
trait Service extends Protocols {
implicit val system: ActorSystem
implicit def executor: ExecutionContextExecutor
implicit val materializer: Materializer
val logger: LoggingAdapter
val routes = {
logRequestResult("model-service") {
pathPrefix("predict") {
(get & path(Segment)) {
features: String =>
complete {
ToResponseMarshallable(predict(features))}}}}}}
Model Serialization
Random Forest in Spark MLlib
MLlib Model Serialization
{
"class": "org.apache.spark.ml.PipelineModel",
"timestamp": 1467653845388,
"sparkVersion": "2.0.0-preview",
"uid": "pipeline_6b4fb08e8fb0",
"paramMap": {
"stageUids": ["quantileDiscretizer_d3996173db25",
"vecAssembler_2bdcd79fe1cf",
"logreg_9d559ca7e208"]
}
}
MLlib Model Serialization
{ "class": "org.apache.spark.ml.classification.LogisticRegressionModel",
"timestamp": 1467653845650,
"sparkVersion": "2.0.0-preview",
"uid": "logreg_9d559ca7e208",
"paramMap": {
"threshold": 0.5,
"elasticNetParam": 0.0,
"fitIntercept": true,
"tol": 1.0E-6,
"regParam": 0.0,
"maxIter": 5,
"standardization": true,
"featuresCol": "features",
"rawPredictionCol": "rawPrediction",
"predictionCol": "prediction",
"probabilityCol": "probability",
"labelCol": "label"}}
Parquet
Packaging
Containerizing with sbt-docker
dockerfile in docker := {
val jarFile: File = sbt.Keys.`package`.in(Compile, packageBin).value
val classpath = (managedClasspath in Compile).value
val mainClass = "com.reactivemachinelearning.PredictiveService"
val jarTarget = s"/app/${jarFile.getName}"
val classpathString = classpath.files.map("/app/" + _.getName)
.mkString(":") + ":" + jarTarget
new Dockerfile {
from("java")
add(classpath.files, "/app/")
add(jarFile, jarTarget)
entryPoint("java", "-cp", classpathString, mainClass)
}
}
Containerizing with sbt-docker
FROM java
ADD 0/spark-core_2.11-2.0.0-preview.jar 1/avro-mapred-1.7.7-hadoop2.jar ...
ADD 166/chapter-7_2.11-1.0.jar /app/chapter-7_2.11-1.0.jar
ENTRYPOINT ["java", "-cp", "/app/spark-core_2.11-2.0.0-preview.jar ...
"com.reactivemachinelearning.PredictiveService"]
Model Servers
Transportation
Model Server in http4s
object Models {
val modelA = HttpService {
case GET -> Root / "a" / inputData =>
val response = true
Ok(s"Model A predicted $response.")
}
val modelB = HttpService {
case GET -> Root / "b" / inputData =>
val response = false
Ok(s"Model B predicted $response.")
}
}
Model Server in http4s
object Client {
val client = PooledHttp1Client()
private def call(model: String, input: String) = {
val target = Uri.fromString(s"http://localhost:8080/models/$model/$input").toOption.get
client.expect[String](target)
}
def callA(input: String) = call("a", input)
def callB(input: String) = call("b", input)
}
Model Server in http4s
def splitTraffic(data: String) = {
data.hashCode % 10 match {
case x if x < 4 => Client.callA(data)
case _ => Client.callB(data)
}
}
Model Server in http4s
object ModelServer extends ServerApp {
val apiService = HttpService {
case GET -> Root / "predict" / inputData =>
val response = splitTraffic(inputData).run
Ok(response)
}
override def server(args: List[String]): Task[Server] = {
BlazeBuilder
.bindLocal(8080)
.mountService(apiService, "/api")
.mountService(Models.modelA, "/models")
.mountService(Models.modelB, "/models")
.start
}
}
Model Server in http4s
import scala.util.Random
val modelC = HttpService {
case GET -> Root / "c" / inputData => {
val workingOk = Random.nextBoolean()
val response = true
if (workingOk) {
Ok(s"Model C predicted $response.")
} else {
BadRequest("Model C failed to predict.")
}
}
}
Model Server in http4s
private def call(model: String, input: String): Task[Response] = {
val target = Uri.fromString(
s"http://localhost:8080/models/$model/$input"
).toOption.get
client(target)
}
def callC(input: String) = call("c", input)
Model Server in http4s
def splitTraffic(data: String) = {
data.hashCode % 10 match {
case x if x < 4 => Client.callA(data)
case x if x < 6 => Client.callB(data)
case _ => Client.callC(data)
}
}
val apiService = HttpService {
case GET -> Root / "predict" / inputData =>
val response = splitTraffic(inputData).run
response match {
case r: Response if r.status == Ok => Response(Ok).withBody(r.bodyAsText)
case r => Response(BadRequest).withBody(r.bodyAsText)
}
}
Model Server in http4s
def splitTraffic(data: String) = {
data.hashCode % 10 match {
case x if x < 4 => Client.callA(data)
case x if x < 6 => Client.callB(data)
case _ => Client.callC(data)
}
}
val apiService = HttpService {
case GET -> Root / "predict" / inputData =>
val response = splitTraffic(inputData).run
response match {
case r: Response if r.status == Ok => Response(Ok).withBody(r.bodyAsText)
case r => Response(BadRequest).withBody(r.bodyAsText)
}
}
Model Server in http4s
private def call(model: String, input: String) = {
val target = Uri.fromString(s"http://localhost:8080/models/$model/$input").toOption.get
client(target).retry(Seq(1 second), {_ => true})
}
BEAM
Erlang
Elixir
Knowledge Maintenance
Circuit Breakers in Erlang/Elixir
def update(user_data) do
{user_id, _} = user_data
case verify_fuse(user_id) do
:ok ->
write_to_db(user_data)
|> parse_db_response(user_id)
:sorry ->
IO.puts "This user can't be updated now. ¯_(ツ)_/¯"
:sorry
end
end
Circuit Breakers in Erlang/Elixir
defp verify_fuse(user_id) do
case :fuse.ask(user_id, :sync) do
{:error, :not_found} ->
IO.puts "Installing"
install_fuse(user_id)
:ok
:blown ->
:sorry
_ -> :ok
end
end
Circuit Breakers in Erlang/Elixir
defp install_fuse(user_id) do
:fuse.install(user_id, {{:standard, 3, 60000}, {:reset, 900000}})
end
Circuit Breakers in Erlang/Elixir
defp write_to_db({_user_id, _data}) do
Enum.random([{:ok, ""}, {:error, "The DB dropped the ball. ಠ_ಠ"}])
end
Circuit Breakers in Erlang/Elixir
defp parse_db_response({:ok, _}, _user_id) do
:ok
end
defp parse_db_response({:error, message}, user_id) do
:fuse.melt(user_id)
IO.puts "Error encountered: #{message}.nMelting the fuse!"
:sorry
end
Circuit Breakers in Erlang/Elixir
def update(user_data) do
{user_id, _} = user_data
case verify_fuse(user_id) do
:ok ->
write_to_db(user_data)
|> parse_db_response(user_id)
:sorry ->
IO.puts "This user can't be updated now. ¯_(ツ)_/¯"
:sorry
end
end
Circuit Breakers in Akka
class DangerousActor extends Actor with ActorLogging {
import context.dispatcher
val breaker =
new CircuitBreaker(
context.system.scheduler,
maxFailures = 5,
callTimeout = 10.seconds,
resetTimeout = 1.minute).onOpen(notifyMeOnOpen())
def notifyMeOnOpen(): Unit =
log.warning("My CircuitBreaker is now open, and will not close for one minute")
}
Circuit Breakers in Lagom
def descriptor: Descriptor = {
import Service._
named("hello").withCalls(
namedCall("hi", this.sayHi),
namedCall("hiAgain", this.hiAgain)
.withCircuitBreaker(CircuitBreaker.identifiedBy("hello2"))
)
}
Deep Learning
Python
Galápagos Nǎo
Diversity in Ecosystems
Evolution
def evolve(nets, generations) do
evolve(nets, generations, &decrement/1)
end
def evolve(nets, generations, count_function) when generations > 0 do
Task.Supervisor.async(GN.TaskSupervisor, fn ->
IO.puts("Generations remaining: #{generations}")
learn_generation(nets)
|> select()
|> evolve(count_function.(generations), count_function)
end)
end
def evolve(nets, _generations, _count_function) do
nets
end
Evolution
def learn_generation(nets) do
clean_nets = strip_empties(nets)
tasks =
Task.Supervisor.async_stream_nolink(
GN.TaskSupervisor,
clean_nets,
&start_and_spawn(&1),
timeout: GN.Parameters.get(__MODULE__, :timeout)
)
generation = for {status, net} <- tasks, status == :ok, do: net
IO.puts(inspect(generation))
generation
end
Evolution
def spawn_offspring(seed_layers, mutation_rate  @mutation_rate) do
duplicate(seed_layers, mutation_rate)
|> remove(mutation_rate)
|> Enum.map(&mutate(&1, mutation_rate))
end
Evolution
def select(pid  __MODULE__, nets) do
cutoffs = cutoffs(nets)
for net <- nets do
complexity = length(net.layers)
level = Enum.min(
[Enum.find_index(cutoffs, &(&1 >= complexity)) + 1,
complexity_levels()])
net_acc = net.test_acc
elite_acc = Map.get(get(level), :test_acc)
if is_nil(elite_acc) or net_acc > elite_acc do
put(pid, level, net)
end
end
Evolution
iex(1)> GN.Selection.get_all()
%{
1 => %GN.Network{
id: "0c2020ad-8944-4f2c-80bd-1d92c9d26535",
layers: [
dense: [64, :softrelu],
batch_norm: [],
activation: [:relu],
dropout: [0.5],
dense: [63, :relu]
],
test_acc: 0.8553
},
2 => %GN.Network{
id: "58229333-a05d-4371-8f23-e8e55c37a2ec",
layers: [
dense: [64, :relu],
Continual Learning
iex(2)> GN.Example.infinite_example()
%Task{
owner: #PID<0.171.0>,
pid: #PID<0.213.0>,
ref: #Reference<0.1968944036.911736833.180535>
}
Generations remaining: infinity
Interactive Evolution
Continual Learning
iex(2)> GN.Example.infinite_example()
%Task{
owner: #PID<0.171.0>,
pid: #PID<0.213.0>,
ref: #Reference<0.1968944036.911736833.180535>
}
Generations remaining: infinity
Interactive Evolution
iex(3)> GN.Selection.get_all() |> Map.get(2) |> GN.Library.put()
iex(4)> GN.Library.get("02b2a947-f888-4abf-b2a5-5df25668b0ee") |> GN.Selection.put_unevaluated()
Galápagos Nǎo Tech Stack
● Elixir
● Apache MXNet/Gluon
● Python
● Export/ErlPort
● Docker
● Microsoft Cognitive Toolkit*
● ONNX support*
* coming soon
Model Serialization Revisited
ONNX
● Open interchange format
● Focused on inference
● Broad and growing support
ONNX Format
message AttributeProto {
enum AttributeType {
UNDEFINED = 0;
FLOAT = 1;
INT = 2;
STRING = 3;
TENSOR = 4;
GRAPH = 5;
FLOATS = 6;
INTS = 7;
STRINGS = 8;
TENSORS = 9;
GRAPHS = 10;
}
ONNXS
iex(1)> {:ok, mnist_data} = File.read "./test/examples/mnist.onnx"
{:ok,
<<8, 3, 18, 4, 67, 78, 84, 75, 26, 3, 50, 46, 52, 40, 1, 58, 227, 206, 1, 10,
199, 80, 18, 12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, 57, 51, 26,
12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, ...>>}
ONNXS
iex(2)> mnist_struct = Onnx.ModelProto.decode(mnist_data)
%Onnx.ModelProto{
doc_string: nil,
domain: nil,
graph: %Onnx.GraphProto{
doc_string: nil,
initializer: [],
input: [
%Onnx.ValueInfoProto{
doc_string: nil,
name: "Input3",
type: %Onnx.TypeProto{
value: {:tensor_type,
%Onnx.TypeProto.Tensor{
elem_type: 1,
shape: %Onnx.TensorShapeProto
...
ONNXS
iex(3)> mnist_updated = %{mnist_struct | model_version: 2}
Thoughts
Model publishing and
serving are hard
problems.
Not all reactive
technologies look like
Erlang.
Reactive patterns are
useful across
toolchains.
Hard problems require
diverse sets of
solutions.
Open standards foster
rich ecosystems.
Wrapping Up
Reactive Machine Learning
Use the code
rmlsnymu
for 40% off the book!
Thanks
Questions
Tools for Making
Machine Learning
more Reactive
Jeff Smith
@jeffksmithjr
jeffsmith.tech

More Related Content

What's hot (20)

PDF
My Top 5 APEX JavaScript API's
Roel Hartman
 
PDF
Re-Design with Elixir/OTP
Mustafa TURAN
 
PPTX
Building Progressive Web Apps for Windows devices
Windows Developer
 
PPTX
Effective C++/WinRT for UWP and Win32
Windows Developer
 
PPTX
Crafting beautiful software
Jorn Oomen
 
PPTX
An ADF Special Report
Luc Bors
 
ODP
An introduction to SQLAlchemy
mengukagan
 
PDF
Symfony World - Symfony components and design patterns
Łukasz Chruściel
 
PPTX
Zero to SOLID
Vic Metcalfe
 
PDF
Introduction to Zend Framework web services
Michelangelo van Dam
 
PDF
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
PPT
Performance improvements tips and tricks
diego bragato
 
PDF
ES2015 workflows
Jarrod Overson
 
KEY
And the Greatest of These Is ... Rack Support
Ben Scofield
 
PPT
Jquery 4
Manish Kumar Singh
 
PDF
Alexey Tsoy Meta Programming in C++ 16.11.17
LogeekNightUkraine
 
PPTX
Cfml features modern coding into the box 2018
Ortus Solutions, Corp
 
PDF
How to Create a l10n Payroll Structure
Odoo
 
PPTX
Why You Should Use TAPIs
Jeffrey Kemp
 
PDF
Php unit the-mostunknownparts
Bastian Feder
 
My Top 5 APEX JavaScript API's
Roel Hartman
 
Re-Design with Elixir/OTP
Mustafa TURAN
 
Building Progressive Web Apps for Windows devices
Windows Developer
 
Effective C++/WinRT for UWP and Win32
Windows Developer
 
Crafting beautiful software
Jorn Oomen
 
An ADF Special Report
Luc Bors
 
An introduction to SQLAlchemy
mengukagan
 
Symfony World - Symfony components and design patterns
Łukasz Chruściel
 
Zero to SOLID
Vic Metcalfe
 
Introduction to Zend Framework web services
Michelangelo van Dam
 
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
Performance improvements tips and tricks
diego bragato
 
ES2015 workflows
Jarrod Overson
 
And the Greatest of These Is ... Rack Support
Ben Scofield
 
Alexey Tsoy Meta Programming in C++ 16.11.17
LogeekNightUkraine
 
Cfml features modern coding into the box 2018
Ortus Solutions, Corp
 
How to Create a l10n Payroll Structure
Odoo
 
Why You Should Use TAPIs
Jeffrey Kemp
 
Php unit the-mostunknownparts
Bastian Feder
 

Similar to Tools for Making Machine Learning more Reactive (20)

PDF
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
ODP
Concurrency on the JVM
Vaclav Pech
 
PDF
Flask patterns
it-people
 
PPTX
Avoiding Callback Hell with Async.js
cacois
 
PDF
DataMapper
Yehuda Katz
 
PDF
Bootstrat REST APIs with Laravel 5
Elena Kolevska
 
PDF
Play vs Rails
Daniel Cukier
 
PDF
用Tornado开发RESTful API运用
Felinx Lee
 
PDF
What's new in jQuery 1.5
Martin Kleppe
 
PPT
GHC Participant Training
AidIQ
 
PDF
Pragmatic Real-World Scala (short version)
Jonas Bonér
 
PDF
Pragmatic Real-World Scala
parag978978
 
PDF
Finch.io - Purely Functional REST API with Finagle
Vladimir Kostyukov
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
Introduction to Scala
Raúl Raja Martínez
 
PPTX
Lambdas puzzler - Peter Lawrey
JAXLondon_Conference
 
KEY
Writing robust Node.js applications
Tom Croucher
 
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
Concurrency on the JVM
Vaclav Pech
 
Flask patterns
it-people
 
Avoiding Callback Hell with Async.js
cacois
 
DataMapper
Yehuda Katz
 
Bootstrat REST APIs with Laravel 5
Elena Kolevska
 
Play vs Rails
Daniel Cukier
 
用Tornado开发RESTful API运用
Felinx Lee
 
What's new in jQuery 1.5
Martin Kleppe
 
GHC Participant Training
AidIQ
 
Pragmatic Real-World Scala (short version)
Jonas Bonér
 
Pragmatic Real-World Scala
parag978978
 
Finch.io - Purely Functional REST API with Finagle
Vladimir Kostyukov
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
Introduction to Scala
Raúl Raja Martínez
 
Lambdas puzzler - Peter Lawrey
JAXLondon_Conference
 
Writing robust Node.js applications
Tom Croucher
 
Ad

More from Jeff Smith (16)

PPTX
Questioning Conversational AI
Jeff Smith
 
PPTX
Neuroevolution in Elixir
Jeff Smith
 
PDF
Building Learning Agents
Jeff Smith
 
PDF
Reactive for Machine Learning Teams
Jeff Smith
 
PDF
Reactive Machine Learning On and Beyond the JVM
Jeff Smith
 
PDF
Bringing Data Scientists and Engineers Together
Jeff Smith
 
PDF
Characterizing Intelligence with Elixir
Jeff Smith
 
PDF
Reactive Learning Agents
Jeff Smith
 
PDF
Spark for Reactive Machine Learning: Building Intelligent Agents at Scale
Jeff Smith
 
PDF
Introducing Reactive Machine Learning
Jeff Smith
 
PDF
Collecting Uncertain Data the Reactive Way
Jeff Smith
 
PDF
Reactive Machine Learning and Functional Programming
Jeff Smith
 
PDF
Huhdoop?: Uncertain Data Management on Non-Relational Database Systems
Jeff Smith
 
PDF
Breadth or Depth: What's in a column-store?
Jeff Smith
 
PDF
Save the server, Save the world
Jeff Smith
 
PDF
NoSQL in Perspective
Jeff Smith
 
Questioning Conversational AI
Jeff Smith
 
Neuroevolution in Elixir
Jeff Smith
 
Building Learning Agents
Jeff Smith
 
Reactive for Machine Learning Teams
Jeff Smith
 
Reactive Machine Learning On and Beyond the JVM
Jeff Smith
 
Bringing Data Scientists and Engineers Together
Jeff Smith
 
Characterizing Intelligence with Elixir
Jeff Smith
 
Reactive Learning Agents
Jeff Smith
 
Spark for Reactive Machine Learning: Building Intelligent Agents at Scale
Jeff Smith
 
Introducing Reactive Machine Learning
Jeff Smith
 
Collecting Uncertain Data the Reactive Way
Jeff Smith
 
Reactive Machine Learning and Functional Programming
Jeff Smith
 
Huhdoop?: Uncertain Data Management on Non-Relational Database Systems
Jeff Smith
 
Breadth or Depth: What's in a column-store?
Jeff Smith
 
Save the server, Save the world
Jeff Smith
 
NoSQL in Perspective
Jeff Smith
 
Ad

Recently uploaded (20)

PDF
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
PDF
Odoo CRM vs Zoho CRM: Honest Comparison 2025
Odiware Technologies Private Limited
 
PPTX
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
PDF
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
PDF
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
PPTX
Platform for Enterprise Solution - Java EE5
abhishekoza1981
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PPTX
Tally software_Introduction_Presentation
AditiBansal54083
 
PPTX
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PPTX
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
PPT
MergeSortfbsjbjsfk sdfik k
RafishaikIT02044
 
PPTX
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
PPTX
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
DOCX
Import Data Form Excel to Tally Services
Tally xperts
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PPTX
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
PDF
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
PPTX
Comprehensive Guide: Shoviv Exchange to Office 365 Migration Tool 2025
Shoviv Software
 
PPTX
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
Odoo CRM vs Zoho CRM: Honest Comparison 2025
Odiware Technologies Private Limited
 
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
Platform for Enterprise Solution - Java EE5
abhishekoza1981
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
Tally software_Introduction_Presentation
AditiBansal54083
 
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
MergeSortfbsjbjsfk sdfik k
RafishaikIT02044
 
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
Import Data Form Excel to Tally Services
Tally xperts
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
Comprehensive Guide: Shoviv Exchange to Office 365 Migration Tool 2025
Shoviv Software
 
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 

Tools for Making Machine Learning more Reactive

  • 1. Tools for Making Machine Learning more Reactive Jeff Smith @jeffksmithjr jeffsmith.tech
  • 13. Akka ● Scala & Java ● Actor model ● Concurrency ● Distribution ● Supervision
  • 15. Model Microservice in Akka HTTP case class Prediction(id: Long, timestamp: Long, value: Double) trait Protocols extends DefaultJsonProtocol { implicit val predictionFormat = jsonFormat3(Prediction) }
  • 16. Model Microservice in Akka HTTP def model(features: Map[Char, Double]) = { val coefficients = ('a' to 'z').zip(1 to 26).toMap val predictionValue = features.map { case (identifier, value) => coefficients.getOrElse(identifier, 0) * value }.sum / features.size Prediction(Random.nextLong(), System.currentTimeMillis(), predictionValue) } def parseFeatures(features: String): Map[String, Double] = { features.parseJson.convertTo[Map[Char, Double]] } def predict(features: String): Prediction = { model(parseFeatures(features)) }
  • 17. Model Microservice in Akka HTTP trait Service extends Protocols { implicit val system: ActorSystem implicit def executor: ExecutionContextExecutor implicit val materializer: Materializer val logger: LoggingAdapter val routes = { logRequestResult("model-service") { pathPrefix("predict") { (get & path(Segment)) { features: String => complete { ToResponseMarshallable(predict(features))}}}}}}
  • 19. Random Forest in Spark MLlib
  • 20. MLlib Model Serialization { "class": "org.apache.spark.ml.PipelineModel", "timestamp": 1467653845388, "sparkVersion": "2.0.0-preview", "uid": "pipeline_6b4fb08e8fb0", "paramMap": { "stageUids": ["quantileDiscretizer_d3996173db25", "vecAssembler_2bdcd79fe1cf", "logreg_9d559ca7e208"] } }
  • 21. MLlib Model Serialization { "class": "org.apache.spark.ml.classification.LogisticRegressionModel", "timestamp": 1467653845650, "sparkVersion": "2.0.0-preview", "uid": "logreg_9d559ca7e208", "paramMap": { "threshold": 0.5, "elasticNetParam": 0.0, "fitIntercept": true, "tol": 1.0E-6, "regParam": 0.0, "maxIter": 5, "standardization": true, "featuresCol": "features", "rawPredictionCol": "rawPrediction", "predictionCol": "prediction", "probabilityCol": "probability", "labelCol": "label"}}
  • 24. Containerizing with sbt-docker dockerfile in docker := { val jarFile: File = sbt.Keys.`package`.in(Compile, packageBin).value val classpath = (managedClasspath in Compile).value val mainClass = "com.reactivemachinelearning.PredictiveService" val jarTarget = s"/app/${jarFile.getName}" val classpathString = classpath.files.map("/app/" + _.getName) .mkString(":") + ":" + jarTarget new Dockerfile { from("java") add(classpath.files, "/app/") add(jarFile, jarTarget) entryPoint("java", "-cp", classpathString, mainClass) } }
  • 25. Containerizing with sbt-docker FROM java ADD 0/spark-core_2.11-2.0.0-preview.jar 1/avro-mapred-1.7.7-hadoop2.jar ... ADD 166/chapter-7_2.11-1.0.jar /app/chapter-7_2.11-1.0.jar ENTRYPOINT ["java", "-cp", "/app/spark-core_2.11-2.0.0-preview.jar ... "com.reactivemachinelearning.PredictiveService"]
  • 28. Model Server in http4s object Models { val modelA = HttpService { case GET -> Root / "a" / inputData => val response = true Ok(s"Model A predicted $response.") } val modelB = HttpService { case GET -> Root / "b" / inputData => val response = false Ok(s"Model B predicted $response.") } }
  • 29. Model Server in http4s object Client { val client = PooledHttp1Client() private def call(model: String, input: String) = { val target = Uri.fromString(s"http://localhost:8080/models/$model/$input").toOption.get client.expect[String](target) } def callA(input: String) = call("a", input) def callB(input: String) = call("b", input) }
  • 30. Model Server in http4s def splitTraffic(data: String) = { data.hashCode % 10 match { case x if x < 4 => Client.callA(data) case _ => Client.callB(data) } }
  • 31. Model Server in http4s object ModelServer extends ServerApp { val apiService = HttpService { case GET -> Root / "predict" / inputData => val response = splitTraffic(inputData).run Ok(response) } override def server(args: List[String]): Task[Server] = { BlazeBuilder .bindLocal(8080) .mountService(apiService, "/api") .mountService(Models.modelA, "/models") .mountService(Models.modelB, "/models") .start } }
  • 32. Model Server in http4s import scala.util.Random val modelC = HttpService { case GET -> Root / "c" / inputData => { val workingOk = Random.nextBoolean() val response = true if (workingOk) { Ok(s"Model C predicted $response.") } else { BadRequest("Model C failed to predict.") } } }
  • 33. Model Server in http4s private def call(model: String, input: String): Task[Response] = { val target = Uri.fromString( s"http://localhost:8080/models/$model/$input" ).toOption.get client(target) } def callC(input: String) = call("c", input)
  • 34. Model Server in http4s def splitTraffic(data: String) = { data.hashCode % 10 match { case x if x < 4 => Client.callA(data) case x if x < 6 => Client.callB(data) case _ => Client.callC(data) } } val apiService = HttpService { case GET -> Root / "predict" / inputData => val response = splitTraffic(inputData).run response match { case r: Response if r.status == Ok => Response(Ok).withBody(r.bodyAsText) case r => Response(BadRequest).withBody(r.bodyAsText) } }
  • 35. Model Server in http4s def splitTraffic(data: String) = { data.hashCode % 10 match { case x if x < 4 => Client.callA(data) case x if x < 6 => Client.callB(data) case _ => Client.callC(data) } } val apiService = HttpService { case GET -> Root / "predict" / inputData => val response = splitTraffic(inputData).run response match { case r: Response if r.status == Ok => Response(Ok).withBody(r.bodyAsText) case r => Response(BadRequest).withBody(r.bodyAsText) } }
  • 36. Model Server in http4s private def call(model: String, input: String) = { val target = Uri.fromString(s"http://localhost:8080/models/$model/$input").toOption.get client(target).retry(Seq(1 second), {_ => true}) }
  • 37. BEAM
  • 41. Circuit Breakers in Erlang/Elixir def update(user_data) do {user_id, _} = user_data case verify_fuse(user_id) do :ok -> write_to_db(user_data) |> parse_db_response(user_id) :sorry -> IO.puts "This user can't be updated now. ¯_(ツ)_/¯" :sorry end end
  • 42. Circuit Breakers in Erlang/Elixir defp verify_fuse(user_id) do case :fuse.ask(user_id, :sync) do {:error, :not_found} -> IO.puts "Installing" install_fuse(user_id) :ok :blown -> :sorry _ -> :ok end end
  • 43. Circuit Breakers in Erlang/Elixir defp install_fuse(user_id) do :fuse.install(user_id, {{:standard, 3, 60000}, {:reset, 900000}}) end
  • 44. Circuit Breakers in Erlang/Elixir defp write_to_db({_user_id, _data}) do Enum.random([{:ok, ""}, {:error, "The DB dropped the ball. ಠ_ಠ"}]) end
  • 45. Circuit Breakers in Erlang/Elixir defp parse_db_response({:ok, _}, _user_id) do :ok end defp parse_db_response({:error, message}, user_id) do :fuse.melt(user_id) IO.puts "Error encountered: #{message}.nMelting the fuse!" :sorry end
  • 46. Circuit Breakers in Erlang/Elixir def update(user_data) do {user_id, _} = user_data case verify_fuse(user_id) do :ok -> write_to_db(user_data) |> parse_db_response(user_id) :sorry -> IO.puts "This user can't be updated now. ¯_(ツ)_/¯" :sorry end end
  • 47. Circuit Breakers in Akka class DangerousActor extends Actor with ActorLogging { import context.dispatcher val breaker = new CircuitBreaker( context.system.scheduler, maxFailures = 5, callTimeout = 10.seconds, resetTimeout = 1.minute).onOpen(notifyMeOnOpen()) def notifyMeOnOpen(): Unit = log.warning("My CircuitBreaker is now open, and will not close for one minute") }
  • 48. Circuit Breakers in Lagom def descriptor: Descriptor = { import Service._ named("hello").withCalls( namedCall("hi", this.sayHi), namedCall("hiAgain", this.hiAgain) .withCircuitBreaker(CircuitBreaker.identifiedBy("hello2")) ) }
  • 53. Evolution def evolve(nets, generations) do evolve(nets, generations, &decrement/1) end def evolve(nets, generations, count_function) when generations > 0 do Task.Supervisor.async(GN.TaskSupervisor, fn -> IO.puts("Generations remaining: #{generations}") learn_generation(nets) |> select() |> evolve(count_function.(generations), count_function) end) end def evolve(nets, _generations, _count_function) do nets end
  • 54. Evolution def learn_generation(nets) do clean_nets = strip_empties(nets) tasks = Task.Supervisor.async_stream_nolink( GN.TaskSupervisor, clean_nets, &start_and_spawn(&1), timeout: GN.Parameters.get(__MODULE__, :timeout) ) generation = for {status, net} <- tasks, status == :ok, do: net IO.puts(inspect(generation)) generation end
  • 55. Evolution def spawn_offspring(seed_layers, mutation_rate @mutation_rate) do duplicate(seed_layers, mutation_rate) |> remove(mutation_rate) |> Enum.map(&mutate(&1, mutation_rate)) end
  • 56. Evolution def select(pid __MODULE__, nets) do cutoffs = cutoffs(nets) for net <- nets do complexity = length(net.layers) level = Enum.min( [Enum.find_index(cutoffs, &(&1 >= complexity)) + 1, complexity_levels()]) net_acc = net.test_acc elite_acc = Map.get(get(level), :test_acc) if is_nil(elite_acc) or net_acc > elite_acc do put(pid, level, net) end end
  • 57. Evolution iex(1)> GN.Selection.get_all() %{ 1 => %GN.Network{ id: "0c2020ad-8944-4f2c-80bd-1d92c9d26535", layers: [ dense: [64, :softrelu], batch_norm: [], activation: [:relu], dropout: [0.5], dense: [63, :relu] ], test_acc: 0.8553 }, 2 => %GN.Network{ id: "58229333-a05d-4371-8f23-e8e55c37a2ec", layers: [ dense: [64, :relu],
  • 58. Continual Learning iex(2)> GN.Example.infinite_example() %Task{ owner: #PID<0.171.0>, pid: #PID<0.213.0>, ref: #Reference<0.1968944036.911736833.180535> } Generations remaining: infinity
  • 60. Continual Learning iex(2)> GN.Example.infinite_example() %Task{ owner: #PID<0.171.0>, pid: #PID<0.213.0>, ref: #Reference<0.1968944036.911736833.180535> } Generations remaining: infinity
  • 61. Interactive Evolution iex(3)> GN.Selection.get_all() |> Map.get(2) |> GN.Library.put() iex(4)> GN.Library.get("02b2a947-f888-4abf-b2a5-5df25668b0ee") |> GN.Selection.put_unevaluated()
  • 62. Galápagos Nǎo Tech Stack ● Elixir ● Apache MXNet/Gluon ● Python ● Export/ErlPort ● Docker ● Microsoft Cognitive Toolkit* ● ONNX support* * coming soon
  • 64. ONNX ● Open interchange format ● Focused on inference ● Broad and growing support
  • 65. ONNX Format message AttributeProto { enum AttributeType { UNDEFINED = 0; FLOAT = 1; INT = 2; STRING = 3; TENSOR = 4; GRAPH = 5; FLOATS = 6; INTS = 7; STRINGS = 8; TENSORS = 9; GRAPHS = 10; }
  • 66. ONNXS iex(1)> {:ok, mnist_data} = File.read "./test/examples/mnist.onnx" {:ok, <<8, 3, 18, 4, 67, 78, 84, 75, 26, 3, 50, 46, 52, 40, 1, 58, 227, 206, 1, 10, 199, 80, 18, 12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, 57, 51, 26, 12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, ...>>}
  • 67. ONNXS iex(2)> mnist_struct = Onnx.ModelProto.decode(mnist_data) %Onnx.ModelProto{ doc_string: nil, domain: nil, graph: %Onnx.GraphProto{ doc_string: nil, initializer: [], input: [ %Onnx.ValueInfoProto{ doc_string: nil, name: "Input3", type: %Onnx.TypeProto{ value: {:tensor_type, %Onnx.TypeProto.Tensor{ elem_type: 1, shape: %Onnx.TensorShapeProto ...
  • 68. ONNXS iex(3)> mnist_updated = %{mnist_struct | model_version: 2}
  • 70. Model publishing and serving are hard problems.
  • 71. Not all reactive technologies look like Erlang.
  • 72. Reactive patterns are useful across toolchains.
  • 73. Hard problems require diverse sets of solutions.
  • 76. Reactive Machine Learning Use the code rmlsnymu for 40% off the book!
  • 79. Tools for Making Machine Learning more Reactive Jeff Smith @jeffksmithjr jeffsmith.tech