---
title: Realtime Machine Learning predictions with Kafka and H2O.ai
description: "When you start doing some Machine Learning, you go through a batch-oriented\nprocess: you take a dataset, build a Machine Learning model from this data, and\nuse the model to make some predictions on another dataset. Then, you want to\napply this process to streaming data, and this is where"
image: https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-logo-Jan-18-2024-06-08-26-7992-PM.png
---

[Skip to main content](https://blog.ippon.tech/realtime-machine-learning-predictions-wth-kafka-and-h2o#main)

[![IpponLogoKleinBlue](https://blog.ippon.tech/hs-fs/hubfs/IpponLogoKleinBlue.png?width=219&height=64&name=IpponLogoKleinBlue.png) ![IpponLogoKleinBlue](https://blog.ippon.tech/hs-fs/hubfs/IpponLogoKleinBlue.png?width=219&height=64&name=IpponLogoKleinBlue.png) ![IpponLogoKleinBlue](https://blog.ippon.tech/hs-fs/hubfs/IpponLogoKleinBlue.png?width=168&height=49&name=IpponLogoKleinBlue.png) ![IpponLogoKleinBlue](https://blog.ippon.tech/hs-fs/hubfs/IpponLogoKleinBlue.png?width=168&height=49&name=IpponLogoKleinBlue.png)](https://ipponusa.com/)

- [Home](https://ipponusa.com)
- [Show submenu for About About](https://ipponusa.com/about-us) 
    - [Who We Are](https://ipponusa.com/who-we-are)
    - [Careers](https://ipponusa.com/careers)
    - [Show submenu for Our Partners Our Partners](https://ipponusa.com/our-partners/) 
          - [AWS](https://ipponusa.com/our-partners/aws/)
          - [Snowflake](https://ipponusa.com/our-partners/snowflake/)
          - [Databricks](https://ipponusa.com/our-partners/databricks/)
          - [Microsoft](https://ipponusa.com/our-partners/microsoft/)
- [Show submenu for Services Services](https://ipponusa.com/services) 
    - [Snowflake](https://ipponusa.com/service/snowflake-concierge/)
    - [Artificial Intelligence](https://ipponusa.com/service/artificial-intelligence/)
    - [Data & Analytics](https://ipponusa.com/service/data-analytics/)
    - [Cloud Strategy](https://ipponusa.com/service/cloud-strategy/)
    - [Platform Modernization](https://ipponusa.com/service/platform-moderization/)
    - [Product Innovation](https://ipponusa.com/service/product-innovation/)
    - [Operating Model](https://ipponusa.com/service/operating-model/)
- [Blogs](https://blog.ippon.tech/)
- [Success Stories](https://ipponusa.com/success-stories/)
- [Show submenu for Resources Resources](https://ipponusa.com/resources/) 
    - [eBooks](https://ipponusa.com/ebooks/)
    - [The Data Pour](https://info.ippon.tech/the-data-pour)
    - [Videos & Webinars](https://info.ippon.tech/videos-and-webinars)
    - [Media Center](https://ipponusa.com/media-center/)

Search

Open main navigation

Close main navigation

- [Home](https://ipponusa.com)
- Show submenu for About About 
  
    - About
    - [About](https://ipponusa.com/about-us)
    - [Who We Are](https://ipponusa.com/who-we-are)
    - [Careers](https://ipponusa.com/careers)
    - Show submenu for Our Partners Our Partners 
      
          - Our Partners
          - [Our Partners](https://ipponusa.com/our-partners/)
          - [AWS](https://ipponusa.com/our-partners/aws/)
          - [Snowflake](https://ipponusa.com/our-partners/snowflake/)
          - [Databricks](https://ipponusa.com/our-partners/databricks/)
          - [Microsoft](https://ipponusa.com/our-partners/microsoft/)
- Show submenu for Services Services 
  
    - Services
    - [Services](https://ipponusa.com/services)
    - [Snowflake](https://ipponusa.com/service/snowflake-concierge/)
    - [Artificial Intelligence](https://ipponusa.com/service/artificial-intelligence/)
    - [Data & Analytics](https://ipponusa.com/service/data-analytics/)
    - [Cloud Strategy](https://ipponusa.com/service/cloud-strategy/)
    - [Platform Modernization](https://ipponusa.com/service/platform-moderization/)
    - [Product Innovation](https://ipponusa.com/service/product-innovation/)
    - [Operating Model](https://ipponusa.com/service/operating-model/)
- [Blogs](https://blog.ippon.tech/)
- [Success Stories](https://ipponusa.com/success-stories/)
- Show submenu for Resources Resources 
  
    - Resources
    - [Resources](https://ipponusa.com/resources/)
    - [eBooks](https://ipponusa.com/ebooks/)
    - [The Data Pour](https://info.ippon.tech/the-data-pour)
    - [Videos & Webinars](https://info.ippon.tech/videos-and-webinars)
    - [Media Center](https://ipponusa.com/media-center/)
- Search
- [Contact Us](https://ipponusa.com/contact/)

[Contact Us](https://ipponusa.com/contact/)

# Realtime Machine Learning predictions with Kafka and H2O.ai

![Alexis Seigneurin](https://app.hubspot.com/settings/avatar/d41d8cd98f00b204e9800998ecf8427e)

 by [Alexis Seigneurin](https://blog.ippon.tech/author/alexis-seigneurin)

September 6, 2018

![Realtime Machine Learning predictions with Kafka and H2O.ai](https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-logo-Jan-18-2024-06-08-26-7992-PM.png)

[Apache Kafka](https://blog.ippon.tech/tag/apache-kafka/)

<https://blog.ippon.tech/author/aseigneurin/>Sep 06, 2018

<iframe id="{&quot;xdOrigin&quot;:&quot;https://blog.ippon.tech&quot;,&quot;xdChannel&quot;:&quot;4d09d2cc-5a18-48b3-8cd1-a92f8dd392b6&quot;,&quot;framework&quot;:&quot;@linkedin/xdoor-sdk&quot;,&quot;version&quot;:&quot;0.1.176&quot;,&quot;debug&quot;:false}" class="IN-widget IN-widget--iframe" style="vertical-align: bottom; margin: 0px auto; display: block;" title="LinkedIn Embedded Content" xml="lang" src="https://www.linkedin.com/cws/member/public_profile?public_profile_url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Falexisseigneurin&amp;format=inline&amp;related=false&amp;width=286&amp;xdOrigin=https%3A%2F%2Fblog.ippon.tech&amp;xdChannel=4d09d2cc-5a18-48b3-8cd1-a92f8dd392b6&amp;xd_origin_host=https%3A%2F%2Fblog.ippon.tech" name="{&quot;xdOrigin&quot;:&quot;https://blog.ippon.tech&quot;,&quot;xdChannel&quot;:&quot;4d09d2cc-5a18-48b3-8cd1-a92f8dd392b6&quot;,&quot;framework&quot;:&quot;@linkedin/xdoor-sdk&quot;,&quot;version&quot;:&quot;0.1.176&quot;,&quot;debug&quot;:false}" width="1" height="1" frameborder="0" scrolling="no"></iframe>

When you start doing some Machine Learning, you go through a batch-oriented process: you take a dataset, build a Machine Learning model from this data, and use the model to make some predictions on another dataset. Then, you want to apply this process to streaming data, and this is where it can get confusing! Let's see what you can do in streaming and what you cannot do.

# Looking at a use case

To illustrate this article, let's take one of the most common use cases of Machine Learning: estimating prices of real estate ([just like Zillow does](https://www.zdnet.com/article/zillow-machine-learning-and-data-in-real-estate/?ref=blog.ippon.tech)). You have a dataset of **past observations**, with the characteristics and the selling price of some houses:

![](https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-h2o-data-3.png)

You can build a regression model so that, when there is a new house to sell, you can estimate what the selling price will be, e.g. a house of 2000 sqft with a lot of 0.5 acres might sell around $250,000.

The first mistake people make is to think we can update the model when we receive a new house to sell. We can't, because the new piece of data is an **unlabeled** record: we know the characteristics of the house, but we don't know its selling price (yet). It is only once the house has been sold that we can enrich our training dataset with a new record.

The second usual mistake is to think we should update the model every time we have a new labeled record (a house was sold and we know its selling price). Well, we *could*, but it is probably not a good idea to do so. Training a model may require doing some cross-validation, going through a grid-search to optimize our parameters, and we may even try multiple algorithms. All of this is makes the process very resource-intensive. It is also a good idea to have a human verify that the model performs as expected before using it in production. And who knows, the real estate market may be going through a bubble, and you may want to refine your dataset to only keep the last 3 months of data.

Basically, what I am trying to say is that **your Data Scientist should decide *when* to update the model**.

More generally speaking, when you update your model incrementaly, i.e. as you receive new training examples, we talk about [Online Machine Learning](https://en.wikipedia.org/wiki/Online_machine_learning?ref=blog.ippon.tech). However, few algorithms allow that.

# Looking at technologies

To recap the point above:

- The training process should be done in batch, from time to time, with a fixed dataset, and will produce a model.
- A streaming application can use the model (without updating it), and we may need to update the application when a new model is produced.

Let's look at some popular Machine Learning toolkits:

- [scikit-learn](http://scikit-learn.org/?ref=blog.ippon.tech) and [Tensorflow](https://www.tensorflow.org/?ref=blog.ippon.tech): two popular Python libraries.
- [Spark ML](https://spark.apache.org/docs/latest/ml-guide.html?ref=blog.ippon.tech): a library built on top of Apache Spark.
- cloud-hosted Machine Learning services, such as [Google Cloud Machine Learning Engine](https://cloud.google.com/ml-engine/?ref=blog.ippon.tech) or [AWS SageMaker](https://aws.amazon.com/sagemaker/?ref=blog.ippon.tech).
- [H2O.ai](https://www.h2o.ai/?ref=blog.ippon.tech): a mostly-Java based platform.

These are all great options to build a ML model, but let's say you want to use the model to make some predictions in realtime, as events arrive in Kafka, and your application is Java-based:

- scikit-learn and Tensorflow: since these are Python libraries, your best bet is to expose the model on a REST API, and call the API from your Java application. Serving the model - and potentially scaling it - requires some work, though.
- Spark ML: you will most likely have to use Spark Streaming, which comes with its set of challenges (high latency, complexity when updating an application, etc.).
- Cloud-hosted services: these are API-based, and therefore very easy to integrate, but latency might be too high if you need to make your predictions with a very low-latency.
- H2O.ai: this platform allows you to download the model as a POJO (a Java class) that you can integrate in your application. **This is what we are going to use in this post.**

# Creating a ML model with H2O

[H2O.ai](https://www.h2o.ai/?ref=blog.ippon.tech) is an open-source platform for Machine Learning, and the company behind it also offers paid support as well as paid products enterprise products. In this post, we are going to use the free product.

I am not going to explain how to use the H2O platform, and show how to build a model. Instead, follow this [Quick Start Tutorial For Just About Anyone](https://bitbook.io/h2o-ai-quick-start-tutorial-for-just-about-anyone/?ref=blog.ippon.tech). In this tutorial, the author uses the data I showed above, and builds a model with the *gradient boosting machine* algorithm. You should get something like this:

![](https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-h2o-model-2.png)

Go ahead and click on "Download POJO" to get a Java file that looks like this:

![](https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-h2o-pojo-2.png)

# Using the model in a Java application

Now, let's use our model in a Java application (we're actually going to use Kotlin, but this is a JVM-based application).

Start by creating a project, then put the POJO you downloaded earlier under the `src/main/java/` directory. By default, the model belongs to the root package, which is not great, so let's move it to another package. I moved the class to the `com.ippontech.kafkah2o` package:

![](https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-h2o-project-structure-2.png)

We are going to use H2O's Gen Model library to interact with the model, so let's add a dependency in our Gradle build:

```
dependencies {
    compile 'ai.h2o:h2o-genmodel:3.20.0.6'
    // other dependencies...
}
```

(Make sure to use the version that matches your H2O installation.)

We can now load our model, prepare a record, then make a prediction:

```
fun main(args: Array<String>) {
    val rawModel = gbm_2760b04d_9dfd_436c_b780_7bdb2f372d85()
    val model = EasyPredictModelWrapper(rawModel)
    val row = RowData().apply {
        put("sqft", 2342.0)
        put("lot_size_acres", 0.4)
        put("stories", 1.0)
        put("number_bedrooms", 3.0)
        put("number_bathrooms", 3.0)
        put("attached_garage", "yes")
        put("has_pool", "no")
        put("has_kitchen_island", "yes")
        put("main_flooring_type", "hardwood")
        put("has_granite_counters", "yes")
        put("house_age_years", 4.0)
    }
    val prediction = model.predictRegression(row)
    println("Prediction: \$${prediction.value}")
}
```

If we run this code, we get something like:

```
Prediction: $290591.70578645257
```

Great, we just used our Machine Learning model in a standalone application!

# Using the model in a Kafka Streams application

I put together a basic producer that pushes *unlabeled records* to a Kafka topic called `housing`. The data is in JSON:

```
$ kafka-console-consumer --bootstrap-server localhost:9092 --topic housing

{"sqft":2572,"lot_size_acres":0.2318716,"stories":2,"number_bedrooms":1,"number_bathrooms":0,"attached_garage":false,"has_pool":true,"has_kitchen_island":true,"main_flooring_type":"hardwood","has_granite_counters":false,"house_age_years":18}

{"sqft":1256,"lot_size_acres":0.774486,"stories":2,"number_bedrooms":1,"number_bathrooms":2,"attached_garage":false,"has_pool":false,"has_kitchen_island":true,"main_flooring_type":"hardwood","has_granite_counters":false,"house_age_years":3}

{"sqft":2375,"lot_size_acres":0.7467226,"stories":2,"number_bedrooms":4,"number_bathrooms":0,"attached_garage":false,"has_pool":true,"has_kitchen_island":false,"main_flooring_type":"hardwood","has_granite_counters":true,"house_age_years":3}
...
```

We are going to build a [Kafka Streams](https://kafka.apache.org/documentation/streams/?ref=blog.ippon.tech) application to process this stream and make predictions as new records arrive.

The first step is to create a model for our data. We are using a [Kotlin data class](https://kotlinlang.org/docs/reference/data-classes.html?ref=blog.ippon.tech):

```
@JsonInclude(Include.NON_NULL)
data class House(
        val sqft: Int,
        val lot_size_acres: Float,
        val stories: Int,
        val number_bedrooms: Int,
        val number_bathrooms: Int,
        val attached_garage: Boolean,
        val has_pool: Boolean,
        val has_kitchen_island: Boolean,
        val main_flooring_type: String,
        val has_granite_counters: Boolean,
        val house_age_years: Int,
        val selling_price: Int? = null)
```

The `selling_price` property is the value we will predict. We will use it when we output predictions to another Kafka topic.

We can now read the data from the input topic into a `KStream<String, House>`:

```
val streamsBuilder = StreamsBuilder()
val housesStream: KStream<String, House> = streamsBuilder
        .stream("housing", Consumed.with(Serdes.String(), Serdes.String()))
        .mapValues { v -> jsonMapper.readValue(v, House::class.java) }
```

Now, all we have to do to make predictions is to fill in a `RowData` object, making sure all the numeric values are of type `Double`, and booleans are either `yes` or `no`:

```
val predictionsStream: KStream<String, House> = housesStream.mapValues { _, h ->
    val row = RowData().apply {
        put("sqft", h.sqft.toDouble())
        put("lot_size_acres", h.lot_size_acres.toDouble())
        put("stories", h.stories.toDouble())
        put("number_bedrooms", h.number_bedrooms.toDouble())
        put("number_bathrooms", h.number_bathrooms.toDouble())
        put("attached_garage", h.attached_garage)
        put("has_pool", h.has_pool.toYesNo())
        put("has_kitchen_island", h.has_kitchen_island.toYesNo())
        put("main_flooring_type", h.main_flooring_type)
        put("has_granite_counters", h.has_granite_counters.toYesNo())
        put("house_age_years", h.house_age_years.toDouble())
    }
    val prediction = model.predictRegression(row).value.toInt()
    h.copy(selling_price = prediction)
}
```

Notice that I used a [Kotlin extension function](https://kotlinlang.org/docs/reference/extensions.html?ref=blog.ippon.tech) to convert booleans:

```
fun Boolean.toYesNo(): String = when (this) {
    true -> "yes"
    else -> "no"
}
```

I also kept the model as a member variable to avoid instantiating it multiple times:

```
private val rawModel = gbm_2760b04d_9dfd_436c_b780_7bdb2f372d85()
private val model = EasyPredictModelWrapper(rawModel)
```

We can finally write the KStream back to a Kafka topic:

```
predictionsStream
        .mapValues { _, p -> jsonMapper.writeValueAsString(p) }
        .to("predictions", Produced.with(Serdes.String(), Serdes.String()))
```

Now, if we look at the output topic, we can see the input data enhanced with predicted selling prices:

```
$ kafka-console-consumer --bootstrap-server localhost:9092 --topic predictions

{"sqft":2572,"lot_size_acres":0.2318716,...,"selling_price":297625}

{"sqft":1256,"lot_size_acres":0.774486,...,"selling_price":254118}

{"sqft":2375,"lot_size_acres":0.7467226,...,"selling_price":303408}
...
```

# Conclusion

We saw in this post how we can embed a Machine Learning model in a Kafka Streams application. The model was built outside of the streaming pipeline, and the generated POJO was completely independant from the platform where the model was trained.

There are pros and cons to embedding a model in your application, as opposed to serving a model through an API:

- pros: 
    - predictions are made with very low latency
    - no external dependency, making it a very robust deployment model
- cons: 
    - harder to update the model: you have to update the application as well
    - A/B testing of different models is also more difficult.

Hopefully this article lifts some interrogations about how to use Machine Learning in streaming. Let me know if it helped!

The code used in this post can be found [here](https://github.com/aseigneurin/kafka-tutorial-kafka-h2o?ref=blog.ippon.tech).

## Related Articles

##### [![Event-Driven Architecture:Getting Started with Kafka (part 2)](https://blog.ippon.tech/hs-fs/hubfs/Imported_Blog_Media/Event-Driven-Architecture-Getting-Started-with-Kafka-Part-2-2.png?width=520&height=294&name=Event-Driven-Architecture-Getting-Started-with-Kafka-Part-2-2.png) Data • November 2, 2021 Event-Driven Architecture:Getting Started with Kafka (part 2) 9 min read](https://blog.ippon.tech/event-driven-architecture-getting-started-with-kafka-part-2)

##### [![Event-Driven Architecture:Getting Started with Kafka (part 1)](https://blog.ippon.tech/hs-fs/hubfs/Imported_Blog_Media/Event-Driven-Architecture-Getting-Started-with-Kafka-Part-1-3.png?width=520&height=294&name=Event-Driven-Architecture-Getting-Started-with-Kafka-Part-1-3.png) Data • October 26, 2021 Event-Driven Architecture:Getting Started with Kafka (part 1) 9 min read](https://blog.ippon.tech/event-driven-architecture-getting-started-with-kafka-part-1)

##### [![Confluent & Twitter4j Tutorial](https://blog.ippon.tech/hs-fs/hubfs/Imported_Blog_Media/twitterToKafka-3.png?width=520&height=294&name=twitterToKafka-3.png) Data • June 7, 2019 Confluent & Twitter4j Tutorial 6 min read](https://blog.ippon.tech/confluent-kafka-twitter4j)

### Comments

### Subscribe to Our Blog!

Stay informed with the latest insights and updates by signing up for our weekly blog newsletter – delivered straight to your inbox!

[Back to blog homepage »](https://blog.ippon.tech/)

![IpponLogoKleinBlue](https://blog.ippon.tech/hs-fs/hubfs/IpponLogoKleinBlue.png?width=247&height=73&name=IpponLogoKleinBlue.png "IpponLogoKleinBlue")

Ippon is a consulting and expertise firm, who is convinced that technology is a source of progress for society. We help our clients leverage their digital assets to design an appropriate strategy and deploy their transformation roadmap at scale.

#### Navigation

- [Home](https://ipponusa.com/)
- [About](https://ipponusa.com/about-us/)
- [Services](https://ipponusa.com/services/)
- [Blogs](https://blog.ippon.tech/?__hstc=223043268.1036d82247623b329dfefe4e92697801.1714729179243.1714729179243.1714729179243.1&__hssc=223043268.2.1714729179244&__hsfp=803678701)
- [eBooks](https://ipponusa.com/ebooks/)
- [The Data Pour](https://info.ippon.tech/the-data-pour?__hstc=223043268.1036d82247623b329dfefe4e92697801.1714729179243.1714729179243.1714729179243.1&__hssc=223043268.2.1714729179244&__hsfp=803678701)

[Contact Us](https://ipponusa.com/contact/)

[Join Us](https://ipponusa.com/careers/)

#### Services

- [Data & Analytics](https://ipponusa.com/service/data-analytics/)
- [Cloud Strategy](https://ipponusa.com/service/cloud-strategy/)
- [Artificial Intelligence](https://ipponusa.com/service/artificial-intelligence/)
- [Operating Model](https://ipponusa.com/service/operating-model/)
- [Platform Modernization](https://ipponusa.com/service/platform-moderization/)
- [Product Innovation](https://ipponusa.com/service/product-innovation/)

#### Ippon International

- [France](https://fr.ippon.tech/?__hstc=223043268.1036d82247623b329dfefe4e92697801.1714729179243.1714729179243.1714729179243.1&__hssc=223043268.2.1714729179244&__hsfp=803678701)
- [Australia](https://au.ippon.tech/?__hstc=223043268.1036d82247623b329dfefe4e92697801.1714729179243.1714729179243.1714729179243.1&__hssc=223043268.2.1714729179244&__hsfp=803678701)

- #### Contact
- Ippon Technologies  
  [3431 West Leigh Street Richmond, VA 23230, USA](https://maps.app.goo.gl/RySm6SAwZnsxeiLz9)
- [(844) 477- 6687](tel:8444776687)
- [Sales@ipponusa.com](mailto:Sales@ipponusa.com)

<https://www.facebook.com/IpponUSA/> <https://www.youtube.com/c/ipponusa> <https://www.linkedin.com/company/ippon-technology>

©Copyright 2024 Ippon USA. All Rights Reserved.   |   [Terms and Conditions](https://ipponusa.com/privacy-policy/)   |   [Privacy Policy](https://ipponusa.com/privacy-policy/)   |   [Website by Skol Marketing](https://skolmarketing.com/)

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Alexis Seigneurin",
    "url" : "https://blog.ippon.tech/author/alexis-seigneurin"
  },
  "dateModified" : "2024-01-29T17:41:19.043Z",
  "datePublished" : "2018-09-06T14:34:00.000Z",
  "headline" : "Realtime Machine Learning predictions with Kafka and H2O.ai",
  "image" : [ "https://blog.ippon.tech/hubfs/Imported_Blog_Media/kafka-logo-Jan-18-2024-06-08-26-7992-PM.png" ],
  "mainEntityOfPage" : {
    "@id" : "https://blog.ippon.tech/realtime-machine-learning-predictions-wth-kafka-and-h2o",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://blog.ippon.tech/hubfs/logo_SVG.svg"
    },
    "name" : "Ippon Technologies"
  }
}
```