<jupyter_start><jupyter_text>A fast and dirty intro to running a model via web serviceHave you ever needed to score data with a predictive model in (near) real time, using a remote server/machine? While not a statistical or machine learning topic, it's one that I struggled with for a while, and haven't found many resources for.In this post, we're going to assume an understanding of predictive modeling and python, to focus on a simple way to set up a web service that can recieve data and return model predictions over the internet.This way is by no means definitive, but is straightforward and effective. ___ [Part 1: Model](http://spencercarter.info/docs/model_web_service_flask_p1.ipynb)To get our model going, let's just fit a simple LASSO with K-fold on the boston dataThis is a quick model just to get something running in our web service. It's roughly based on [This example code from sklearn](http://scikit-learn.org/stable/auto_examples/feature_selection/plot_select_from_model_boston.htmlsphx-glr-auto-examples-feature-selection-plot-select-from-model-boston-py).<jupyter_code>import sklearn as sk
import numpy as np
from sklearn.datasets import load_boston
from sklearn.linear_model import LassoCV
import pandas as pd
from flask import Flask
from flask import request
import requests
import pickle
from time import time

# Load up the Mass data... I like keeping things in pandas DFs
mass = load_boston()

# Lowecase the predictor names and send the data to Pandas
predictors = [var.lower() for var in mass.feature_names]
X = pd.DataFrame(mass['data'], columns=predictors)
y = pd.Series(mass['target']) # medv

# Run a 3-fold CV LASSO with 10 weights chosen by steepest descent
lasso = LassoCV(n_alphas=10, normalize=True, cv=3)

print("Fitting model...")
lasso.fit(X,y)

print("Model fit. R-Squared = {0:0.2f}%".format(100*lasso.score(X,y)))<jupyter_output>Fitting model...
Model fit. R-Squared = 71.06%<jupyter_text>This is enough for our demonstration... We're assuming a basic familiarity with modeling concepts like variable selection and use of validation data.Now, we're going to save the current objects down to disk so our listener and sender can access them. While everything is together in this document, the source code I've made available is split into Model, Listener, and Sender<jupyter_code># A couple simple pickle functions
def pickle_me(obj, outfile):
    with open(outfile, 'wb') as f:
        pickle.dump(obj, f, protocol=pickle.HIGHEST_PROTOCOL)
    return None

def unpickle_me(infile):
    with open(infile, 'rb') as f:
        unpickled = pickle.load(f)
    return unpickled
               
to_pickle = {'X':X, 'lasso':lasso, 'dtypes':X.dtypes, 'predictors':predictors}
pickle_me(to_pickle, 'model_web_service.pickle')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08180839612486544, 'fraction_numerical': 0.006458557588805167, 'mean_word_length': 4.91932059447983, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '378044', 'license': 'MIT', 'n_tokens_mistral': 865, 'n_tokens_neox': 828, 'n_words': 335, 'path': 'model_web_service_flask_post_1.ipynb', 'repo_name': 'spencercarter/blog_content', 'size': '2787'}