<jupyter_start><jupyter_text>This is one of the Objectiv example notebooks. For more examples visit the [example notebooks](https://objectiv.io/docs/modeling/example-notebooks/) section of our docs. The notebooks can run with the demo data set that comes with the our [quickstart](https://objectiv.io/docs/home/quickstart-guide/), but can be used to run on your own collected data as well.All example notebooks are also available in our [quickstart](https://objectiv.io/docs/home/quickstart-guide/). With the quickstart you can spin up a fully functional Objectiv demo pipeline in five minutes. This also allows you to run these notebooks and experiment with them on a demo data set. The open model hub supports logistic regression on Bach data objects. A logistic regression model can be fitted, values can be predicted and results can be tested directly on the full data set in the database. Note that for fitting the model data is extracted from the database under the hood.  Import the required packages for this notebookThe open model hub package can be installed with `pip install objectiv-modelhub` (this installs Bach as well).  If you are running this notebook from our quickstart, the model hub and Bach are already installed, so you don't have to install it separately.<jupyter_code>from modelhub import ModelHub
from bach import display_sql_as_markdown<jupyter_output><empty_output><jupyter_text>At first we have to instantiate the Objectiv DataFrame object and the model hub.<jupyter_code># instantiate the model hub
modelhub = ModelHub(time_aggregation='%Y-%m-%d')
# get the Bach DataFrame with Objectiv data
df = modelhub.get_objectiv_dataframe(start_date='2022-02-15', end_date='2022-05-16')<jupyter_output><empty_output><jupyter_text>If you are running this example on your own collected data, setup the db connection like this and replace above cell:<jupyter_code># df = modelhub.get_objectiv_dataframe(db_url='postgresql://USER:PASSWORD@HOST:PORT/DATABASE',
#                                     start_date='2022-06-01',
#                                     end_date='2022-06-30',
#                                     table_name='data')<jupyter_output><empty_output><jupyter_text>Creating a feature set to predict user behavior Data collected with Objectiv's tracker is [well-structured & consistent](https://objectiv.io/docs/taxonomy), which makes it ideal for various machine learning applications. Machine learning models can be applied directly without cleaning, transformations or using complex tooling. In this example, we show how you can predict user behavior with the supported logistic regression model. Examples of predictions that you can create:- Will a user convert?- Will a user start using a specific product feature or area?- Will a user have a long active session duration?For simple demonstration purposes, we will predict if users on our own [website](https://www.objectiv.io) will reach the [modeling section of our docs](https://objectiv.io/docs/modeling/), by looking at interactions that users have with all the other main sections of our website.We create a data set that counts the number of clicks per user in each section of our website. We obtain the main sections by extracting the [root location](https://objectiv.io/docs/taxonomy/reference/location-contexts/RootLocationContext/) from the location stack. It is similar data set to the one used in the ['Bach and sklearn'](https://objectiv.io/docs/modeling/example-notebooks/machine-learning/) example. Note that this is a small and simple data set used just for demonstration purposes of the logistic regression functionality, and not so much the model results itself. For the ins and outs on feature engineering see our [feature engineering example](https://objectiv.io/docs/modeling/example-notebooks/feature-engineering/).<jupyter_code># extract the root location from the location stack
df['root'] = df.location_stack.ls.get_from_context_with_type_series(type='RootLocationContext', key='id')
# only look at press events and count the root locations
features = df[(df.event_type=='PressEvent')].groupby('user_id').root.value_counts()
# unstack the series, to create a DataFrame with the number of clicks per root location as columns
features_unstacked = features.unstack(fill_value=0)<jupyter_output><empty_output><jupyter_text>Sample the dataWe take a 10% sample of the full data that we will use to train the model on. This limits data processing and speeds up the fitting procedure. After the model is fitted, it can be used to predict the labels for the _entire_ data set.<jupyter_code>features_set_sample = features_unstacked.get_sample('test_lr_sample', sample_percentage=10, overwrite=True, seed=42)<jupyter_output><empty_output><jupyter_text>Using a logistic regression we will predict whether a user clicked in the modeling section or not. We will predict this by the number of clicks in any of the other sections. `X` is a Bach DataFrame that contains the explanatory variables. `y` is a Bach SeriesBoolean with the labels we want to predict.<jupyter_code>y_column = 'modeling'
y = features_set_sample[y_column] > 0
X = features_set_sample.drop(columns=[y_column])<jupyter_output><empty_output><jupyter_text>Show the first lines of `X` and `y`.<jupyter_code>X.head()
y.head()<jupyter_output><empty_output><jupyter_text>Instantiating the logistic regression modelWe can instantiate the logistic regression model from the model hub. Since the model is based on sklearn's version of LogisticRegression, it can be instantiated with any parameters that sklearn's LogisticRegression [supports](    https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html). In our example we instantiate it with ``fit_intercept=False``<jupyter_code>lr = modelhub.get_logistic_regression(fit_intercept=False)<jupyter_output><empty_output><jupyter_text>Fitting the modelThe `fit` method fits a model to the passed data. This method extracts the data from the database under the hood.<jupyter_code>lr.fit(X, y)<jupyter_output><empty_output><jupyter_text>Accuracy and predictingAll following operations are carried out directly on the database. Therefore, they can be exported to SQL statements so it can be used in for example your BI tooling.<jupyter_code>lr.score(X, y)<jupyter_output><empty_output><jupyter_text>The model has the same attributes as the Logistic Regression model from sklearn.<jupyter_code># show the coefficients of the fitted model
lr.coef_<jupyter_output><empty_output><jupyter_text>Create columns for the predicted values and labels in the sampled data set. Labels `True` if the probability is over .5.<jupyter_code>features_set_sample['predicted_values'] = lr.predict_proba(X)
features_set_sample['predicted_labels'] = lr.predict(X)
# show the sampled data set, including predictions
features_set_sample.head(20)<jupyter_output><empty_output><jupyter_text>Unsample and view the SQLThe data can be unsampled and viewed as an SQL statement. `features_set_full` and the SQL statement for this DataFrame are for the full unsampled data set including the predicted values.<jupyter_code>features_set_full = features_set_sample.get_unsampled()<jupyter_output><empty_output><jupyter_text>Get the sql statement for the _full_ data set including the predicted values.<jupyter_code>display_sql_as_markdown(features_set_full)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07057869118442402, 'fraction_numerical': 0.005813953488372093, 'mean_word_length': 5.651978417266187, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 58, 'https://': 10, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '454809', 'license': 'Apache-2.0', 'n_tokens_mistral': 2066, 'n_tokens_neox': 1980, 'n_words': 814, 'path': 'notebooks/model-hub-logistic-regression.ipynb', 'repo_name': 'objectiv/objectiv-analytics', 'size': '7396'}