STARBUCKS SUPER PROMO
By: Arturo Gonzalez
Tags: Capstone, Machine Learning, Starbucks, Udacity, Scikit Learn

B. portfolio.json — Promotions information:

portfolio Data Frame

This is a straight forward data set, which has information about the Starbucks’s promotions sent to its clients. There are 10 offers classified in 3 types: bogo , informational and discount and there are no Nan values. I want to highlight the importance of the duration column, it could help us to relate the promotion with a transaction.

C. transcript.json — Timeline / Events:

transcript Data Frame

This is the more interesting dataset, it contains a timeline with the events of all the offers for each client and the amount of the transactions. If a transaction and a promo were completed in the same moment (time column), we can consider that the value in the transaction is the amount the customer has paid to complete the promotion. Here is a list of the events:

events

There are 4 possible sequences for a promotion:

table sequence promotion

It’s also important to note that in the ‘value’ column there is a dictionary containing the offers id, the amount of the transaction and the reward when an offer is completed.

3. defining the model

Before modifying the data, it’s important to define the type of model and the evaluation metrics based on the problem we are addressing: How much a customer is willing to pay based on the type of promotion and demographics.

Since we are going to predict continuous values (“how much a customer is willing to pay”) a good first approach is to use a regression model. My first attempt was a simple Linear regression model, but as you will see in the following sections, there were many outliers that affected the prediction. For this reason Support Vector Regression (SVR) seems a better fit for the job, since it finds a function representing the data within a margin of error (epsilon), where most of the points can be found inside this margin, making SVR a stronger model to treat outliers than other regression models. You can find more information about SVR in this blogpost by Tom Sharp

image taken from here

To evaluate the model we can do a simple cross validation technique taking a part of the training data to get predictions from the trained model and compare it with the actual values(y_test)

To measure how well the model fits we can measure R2 score and the Adjusted R-Squared (same as explained_variance_score in Scikit-learn). The first one is the Coefficient of Determination, which is a good measure to determine how well the model fits the dependent variables.

However, R2 score does not take into consideration overfitting, for these reason we can also calculate the Adjusted R-Squared, wish is similar to the R2 score but it takes into account the Mean of Error, that reflects the tendency of the estimator (how biased is the model). Basically If R2 score is equal to Adjusted R-Squared the mean of error is 0.00. If R2 Square is roughly the same as the Adjusted R-Squared we can conclude that the model is quite robust in this matter. The following formula was taken from this post.

R2 score = 1 — [(Sum of Squared Residuals / n) / Variancey_actual] Adjusted R-Squared = 1 — [{(Sum of Squared Residuals-Mean Error) / n} / Variancey_actual]

4. data pre-processing (cleaning and transforming data)

conceptual dataframe

To create a dataset that fits into a SVD model, all features must have numeric values. To explain the modifications made to the dataset I divided these sections in three parts, each of them explains one part of the ‘conceptual dataset’ shown above.

a . Demographics:

As we saw in data exploration, we can find the demographic information in the profile Data Frame, where have the following features:

‘id’ will help us merge the information with the other datasets.

‘age’ and ‘income’ are numerical values that don’t need to be change, for the moment.

‘became_member_on’ doesn’t give us demographics information about the user, thus we can drop this column.

‘gender’ . We have to convert these features into numerical values. To do this, we can do One Hot Encoding this feature to create three columns for each value (F , M , O).

b . Amount of the transaction (y):

To obtain the value a user paid to complete a promotion, we can extract this value from the transactions that were made. As we can see in the table below (red squares), when a promotion is completed there is a transaction at the same time that has the value that the user paid to complete this offer, thus the first step could be to merge this rows to have the amount with each completed offer.

But there is a tricky part (green square), there are some offers that are classified as ‘informational’ that does not have an ‘offer completed’ event, thus we can’t link the Informational offer with a transaction ( first time I try to create the data frame, all the transaction values were $0.0 in the informational offers type).

To get the transaction values for this type of promotion we have to check if there is a transaction during the duration of the promotion ( in the portfolio dataFrame). We can assume that the transaction made by the user after he or she sees the promotion was influenced by this offer, if it’s still active. In the example below we can see this client saw the informational offer in the hour 216, and made a transaction 6 hours after. Because this offer has a duration of 72 hours we can relate the amount of this transaction with this promotion.