<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
>
	<channel>
		<title>Saloua Litayem, Girly Geek</title>
		<description></description>		
		<sy:updatePeriod>daily</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<link></link>
		<atom:link href="/blog/atom.xml" rel="self" type="application/rss+xml" />
		<lastBuildDate>Tue, 04 Aug 2020 00:00:00 +0000</lastBuildDate>
		
		
			<item>
				<title>Customers churn prediction for Sparkify music service</title>
				
				
					<description>&lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/churn.png&quot; alt=&quot;customer churn&quot; height=&quot;85%&quot; width=&quot;85%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Generally, the ability to accurately predict future customer churn rates is &lt;a href=&quot;https://baremetrics.com/academy/churn-prediction-can-improve-business&quot;&gt;necessary&lt;/a&gt; for the business. It enables it to &lt;a href=&quot;https://www.profitwell.com/blog/churn-prediction&quot;&gt;secure&lt;/a&gt; valuable customers helping anticipate and prevent from churn trends.&lt;/p&gt;

&lt;p&gt;Taking action to secure the customer’s time and attention, and bring it back to the product will increase engagement. And once product engagement is increased, the business will lose less customer.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h2 id=&quot;churn-kills-businesses-prevention-keeps-them-healthy&quot;&gt;Churn kills businesses; prevention keeps them healthy&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;The article presents a Customer Churn Prediction Model project done in the context of &lt;a href=&quot;https://www.udacity.com/course/data-scientist-nanodegree--nd025&quot;&gt;Udacity Data Science Nanodegree&lt;/a&gt; Program.&lt;/p&gt;

&lt;h1 id=&quot;business-understanding&quot;&gt;Business Understanding&lt;/h1&gt;

&lt;p&gt;We are assuming a hypothetical music streaming service (like spotify) called Sparkify.
The users of the service can use either the Premium or the Free Tier subscription. The premium plan with the monthly fees payment enables the use of the service without any advertisements between the songs.&lt;/p&gt;

&lt;p&gt;At any point the users can do any of the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Upgrade from the free tier to the Premium subscription&lt;/li&gt;
  &lt;li&gt;Downgrade from the Premium subscription to the free tier.&lt;/li&gt;
  &lt;li&gt;Drop their account and leave the service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/customers_attrition.png&quot; alt=&quot;customer churn&quot; height=&quot;40%&quot; width=&quot;30%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The aim here is to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;analyse the data,&lt;/li&gt;
  &lt;li&gt;extract insights helping to identify churn indicators&lt;/li&gt;
  &lt;li&gt;and then build a Machine Learning model helping to identify potential churning customers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data analysis, feature engineering and model building was implemented using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PySpark&lt;/code&gt;. This can be found &lt;a href=&quot;https://github.com/slitayem/sparkify_dsnd&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The value of having a predictive model for customer attrition is mainly in identifying customer churn risk where we don’t already know that a risk exists.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Retaining existing customers circumvents the costs of seeking new and potentially risky customers, and allows organizations to focus more accurately on the needs of the existing customers by building relationships.&lt;/p&gt;

&lt;h1 id=&quot;data&quot;&gt;Data&lt;/h1&gt;

&lt;p&gt;The used data contains the user activity events logs happening in the service. Those contain visited pages, service upgrade or downgrade events, demographic information and events timestamps.&lt;/p&gt;

&lt;p&gt;Here are the events key attributes&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;|-- artist: artist name
|-- auth: authentication status
|-- gender
|-- itemInSession: Number of items in the session
|-- length: double (nullable = true)
|-- level: users subscription level
|-- page: svisited page
|-- registration: registration date
|-- ts: levent timestamp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The presented data analysis was performed on a subset of the data (~28K events records). The data timespan is 63 days.&lt;/p&gt;

&lt;h1 id=&quot;data-cleaning&quot;&gt;Data Cleaning&lt;/h1&gt;

&lt;p&gt;8346 Events with empty string as UserId were removed&lt;/p&gt;

&lt;h1 id=&quot;data-exploration&quot;&gt;Data Exploration&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/eda.png&quot; alt=&quot;&quot; height=&quot;60%&quot; width=&quot;60%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;churn-indicators&quot;&gt;Churn indicators&lt;/h2&gt;

&lt;p&gt;We define churning customers as the users who either downgraded their subscription plan or canceled their account. In other words, a churned customer is one who visited one of the service pages &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cancellation Confirmation&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Submit Downgrade&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Following the above definition, the service churn rate is equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;41%&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/account_type_churn.png&quot; alt=&quot;account type&quot; height=&quot;40%&quot; width=&quot;40%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;customers registered for a longer period of time are less likely to churn (Loyal/Engaged).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/account_age_churners.png&quot; alt=&quot;loyal customers&quot; height=&quot;75%&quot; width=&quot;75%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;usage_days&quot;&gt;Percentage of the users function of the service usage period&lt;/h2&gt;

&lt;p&gt;Checking the service usage over the time before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;churning event&lt;/code&gt;, we observe that around &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;96%&lt;/code&gt; of the users have an account for at least &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20 days&lt;/code&gt;.
&lt;img src=&quot;/img/blog/2020-08-04/service_usage_age.png&quot; alt=&quot;account age&quot; height=&quot;55%&quot; width=&quot;55%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Keeping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~96% of the users&lt;/code&gt; (age greater than 20 days) should be sufficient to have a feature reflecting the service usage distribution over the time before churn event (here the last 20 days).&lt;/p&gt;

&lt;h2 id=&quot;number-of-visits-per-page&quot;&gt;Number of visits per page&lt;/h2&gt;
&lt;p&gt;Now let’s have a look at the pages visit. We observe that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;82%&lt;/code&gt; of the events are for the page &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NextSong&lt;/code&gt;. Then, to be able to clearly visualize the pages visits count we decide to filter out the `NextSong page.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/page_visits.png&quot; alt=&quot;page visits&quot; height=&quot;75%&quot; width=&quot;75%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We observe that most of the page visit counts can have an effect on the user engagement e.g &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsDown&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Roll Advert&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NextSong&lt;/code&gt;. Let’s see how those pages visits are having a discriminative role to distinguish between Churning and Engaged customers. This either with the customer interactions on the platform or the number of visits to some of the pages like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; page.&lt;/p&gt;

&lt;h3 id=&quot;roll-adverts-distribution-per-user-type&quot;&gt;Roll adverts distribution per user type&lt;/h3&gt;
&lt;p&gt;&lt;mark style=&quot;background-color: rgba(171, 205, 239, 0.6)&quot;&gt; Engaged users tend to have less Roll Adverts than the Churning users.&lt;/mark&gt;This might be a good indicator to predict if user is likely to churn if he gets a high number of advertisements.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/roll_adverts.png&quot; alt=&quot;&quot; height=&quot;55%&quot; width=&quot;55%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It appears that on average each of the customers type got the same number of error pages. Let’s check the visits to the Thumbs Up and Down page also the number of sessions per user that could reflect how active is the customer in using the service.&lt;/p&gt;

&lt;h3 id=&quot;number-of-errors-distribution-per-user-type&quot;&gt;Number of errors distribution per user type&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/errors_distribution.png&quot; alt=&quot;&quot; height=&quot;60%&quot; width=&quot;60%&quot; class=&quot;center-image&quot; /&gt;
For a number of errors higher than 6, the number of chruning users is higher than the engaged ones. But in average there is no big difference between both users types in term of the number of visited error pages.&lt;/p&gt;

&lt;h3 id=&quot;customers-interactions-on-the-service-platformthumbsupthumbsdown&quot;&gt;Customers interactions on the service platform(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsUp&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsDown&lt;/code&gt;)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/thumbsup_distribution.png&quot; alt=&quot;&quot; height=&quot;60%&quot; width=&quot;60%&quot; class=&quot;center-image&quot; /&gt;
&lt;img src=&quot;/img/blog/2020-08-04/thumbsdown_distribution.png&quot; alt=&quot;&quot; height=&quot;60%&quot; width=&quot;60%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Having a value greater than 200 thumbsUp page visits (combined with other features) might be an indicator for high risk of churn. This is kind of counter intuitive but at the same time this tells us that user that is engaged the most might be the one penalizing the service the most easily.&lt;/p&gt;

&lt;p&gt;In general, it appears that churning users have less interactions in regard of giving a Thumbs Up or a Thumbs Down to a song. But, we observe that pages distribution is chifted towards a &lt;mark style=&quot;background-color: rgba(171, 205, 239, 0.6)&quot;&gt; higher number of thumbsDown page visits for churning users &lt;/mark&gt;. Using the number of thumbsDown pages visit as a feature might help the model to separate the churning users from the engaged ones.&lt;/p&gt;

&lt;h2 id=&quot;service-usage-and-customers-engagement&quot;&gt;Service usage and customers engagement&lt;/h2&gt;
&lt;p&gt;In general, if a customer regularly uses the service, there is nothing to worry about. If, on the other hand, the customer’s usage level drops off, there is a need to find out why it dropped and what to do about it.&lt;/p&gt;

&lt;p&gt;So let’s measure the service usage and engagement of the users in term of number of songs the users listen to and users sessions.&lt;/p&gt;

&lt;h3 id=&quot;average-number-of-items-per-session&quot;&gt;Average Number of items per session&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/avg_items_session.png&quot; alt=&quot;&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It appears that the average number of items per session doesn’t seem to help on average to distinguish between the churning and engaged users. Around 100 sessions, the engaged users average number of items per session tends to be higher than for the churners. We can also see a clear separation between the churned and engaged users starting from 300 items per session.&lt;/p&gt;

&lt;h3 id=&quot;average-number-of-sessions-per-user&quot;&gt;Average number of sessions per user&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/avg_sessions.png&quot; alt=&quot;&quot; height=&quot;60%&quot; width=&quot;60%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The number of sessions per user tends n average to distinguish between the churned and engaged users. The churners tend to have a lower average number of sessions per day than the engaged users. If leaveraged as a feature this might be automatically picked-up by a tree based model e.g decision tree&lt;/p&gt;

&lt;h3 id=&quot;average-service-usage-over-the-last-20-days-nbsessions-and-nbsongs&quot;&gt;Average Service usage over the last 20 days (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nbSessions&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nbSongs&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/avg_songs_20days.png&quot; alt=&quot;&quot; height=&quot;55%&quot; width=&quot;55%&quot; class=&quot;center-image&quot; /&gt;
The number of songs for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;churning&lt;/code&gt; users is decreasing over the last 20 days of logged events in the service. This might be more discriminant when using more data.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/avg_sessions_20days.png&quot; alt=&quot;&quot; height=&quot;55%&quot; width=&quot;55%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We observe that in average the number of sessions for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;churning&lt;/code&gt; users is higher than for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Engaged&lt;/code&gt; users.&lt;/p&gt;

&lt;h1 id=&quot;features-engineering&quot;&gt;Features Engineering&lt;/h1&gt;

&lt;p&gt;In the data exploration step we could extract potential &lt;mark style=&quot;background-color: rgba(171, 205, 239, 0.6)&quot;&gt;indicators&lt;/mark&gt; that can be used to &lt;mark style=&quot;background-color: rgba(171, 205, 239, 0.6)&quot;&gt;distinguish between churning and engaged customers&lt;/mark&gt;.&lt;/p&gt;

&lt;p&gt;We observed that the number of visits to some of the pages could be used as indicators to to know if a customer is likely to churn or not. For example the engaged users were having more interactions on the service platform by visitng more often the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsUp&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsDown&lt;/code&gt; pages. Then we decide to use the following features to reflect the pages visits making difference between both types of users:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Binary feature with value equal to one if the number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsUp&lt;/code&gt; page visits is greater than 20&lt;/li&gt;
  &lt;li&gt;Number of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThumbsDown&lt;/code&gt; page visits&lt;/li&gt;
  &lt;li&gt;Number of Roll Advert Page visits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We observed that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;service usage&lt;/code&gt; and level of engagemnt of the customer can be also a clear indicator. Which helped us to define the following features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Average daily sessions duration&lt;/li&gt;
  &lt;li&gt;Average monthly sessions duration&lt;/li&gt;
  &lt;li&gt;Average daily Number of songs per session&lt;/li&gt;
  &lt;li&gt;Average daily Number of items per session&lt;/li&gt;
  &lt;li&gt;Daily number of songs over the last 20 days (vector of 20 values)&lt;/li&gt;
  &lt;li&gt;Daily number of sessions over the last 20 days (vector of 20 values)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The decision in keeping the usage information over only the last &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20 days&lt;/code&gt; was a result of the check of the percentage of the dataset users that could be kept by number of days the customer have been using sparkify service. See the related analysis and plot in the data exploration part &lt;a href=&quot;#usage_days&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One more feature that could help in having an idea about the customer satisfaction in using the service is to know whether the customer can find the artists songs he wants to listen to or not.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Number of unique artists the user listened to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also decided to have some features to characterize the user subscription:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Last level of the user (Paid or Free)&lt;/li&gt;
  &lt;li&gt;User Account age in days: usage duration since first log event day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We finally have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;54-Dimensional features vector&lt;/code&gt; to represent that would be used for the model training.&lt;/p&gt;
&lt;h1 id=&quot;model-training-and-evaluation&quot;&gt;Model training and evaluation&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/model_workflow.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The purpose of our predictive model is to predict which customers are likely to churn and which not. So it is essentially a binary classification problem. The classes are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Engaged&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Churned&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Classifying Engaged customers as Churning ones might lead the business to taking actions that might confuse the customer and even make them churning the service. It is also important to correctly classify Churning customers. Then our classifier should be precise in classifying both types of customers.&lt;/p&gt;

&lt;h2 id=&quot;model-evaluation-metrics&quot;&gt;Model evaluation metrics&lt;/h2&gt;

&lt;p&gt;Given that churned users are a fairly small subset compared to engaged users, we decided to use F1-Score and AUC metric to evaluate the model performance and select the winning model.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;mark style=&quot;background-color: rgba(171, 205, 239, 0.6)&quot;&gt; F1-Score &lt;/mark&gt;:  balances the tradeoff between the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;precision&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recall&lt;/code&gt; metrics, which is useful in our binary classification problem with the actual classes scale.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;$$
F1 = 2 * \frac{precision * recall}{precision + recall}
$$&lt;/center&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;mark style=&quot;background-color: rgba(171, 205, 239, 0.6)&quot;&gt; area under the ROC curve (AUC) &lt;/mark&gt;: Its advantage over the accuracy is that it is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insensitive to imbalanced classes&lt;/code&gt;. It doesn’t place more emphasis on one class over the other by assessing the overall classification performance by measuring how well predictions are ranked, rather than their absolute values.
&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;trained-models-and-evaluation&quot;&gt;Trained Models and evaluation&lt;/h2&gt;

&lt;p&gt;We tried out various models starting from the simplest one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Logistic Regression&lt;/code&gt; to the more complex ones(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Random Forest&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gradient-Boosted Trees&lt;/code&gt;). We scaled the data to train to avoid that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Logisitc Regression&lt;/code&gt; model performs poorly when features differ widely in scale.
The model were then compared in term of F1-Score and AUC.&lt;/p&gt;

&lt;p&gt;In order to have a less biased estimate of the model performance on unseen data we leveraged  &lt;a href=&quot;https://en.wikipedia.org/wiki/Cross-validation_(statistics)#k-fold_cross-validation&quot;&gt;k-Fold Cross-Validation&lt;/a&gt;(k=3) from Spark Python API &lt;a href=&quot;https://spark.apache.org/docs/latest/api/python/pyspark.ml.html?highlight=crossvalidator#pyspark.ml.tuning.CrossValidator&quot;&gt;CrossValidator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To use the same dataset for the various models algorithms, we performed data scaling using &lt;a href=&quot;https://spark.apache.org/docs/latest/ml-features#standardscaler&quot;&gt;StandardScaler&lt;/a&gt;. That Standardizes features by normalizing each feature to have unit standard deviation and/or zero mean.
Tree-based algorithms are not sensitive to the scale of the features but we need that for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Logistic Regression&lt;/code&gt; Classifier.&lt;/p&gt;

&lt;h3 id=&quot;hyperparameters-tuning&quot;&gt;Hyperparameters Tuning&lt;/h3&gt;

&lt;p&gt;To find the optimal hyperparameters of each of the tried models , we leveraged &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Grid Search&lt;/code&gt;. We then used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AUC metric&lt;/code&gt; to select the best model parameters and retrain the model on the training dataset (without the K-Fold data sampling).&lt;/p&gt;

&lt;p&gt;Here are the parameters used for the models:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://spark.apache.org/docs/latest/mllib-linear-methods.html#logistic-regression&quot;&gt;Logistic Regression&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;elasticNetParam&lt;/strong&gt; ElasticNet mixing parameter. In in range [0, 1]. 0 for L2 penalty and 1 for an L1 penalty, default=0.0: &lt;strong&gt;[0.1, 0.5]&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;maxIter&lt;/strong&gt; Maximum number of iterations: &lt;strong&gt;[20, 70]&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/lr_params.png&quot; alt=&quot;&quot; height=&quot;40%&quot; width=&quot;40%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://spark.apache.org/docs/latest/ml-classification-regression.html#random-forests&quot;&gt;Random Forest&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;maxDepth&lt;/strong&gt; maximum tree depth, default=5: &lt;strong&gt;[4, 5, 7]&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;numTrees&lt;/strong&gt; Number of Trees, default=20: &lt;strong&gt;[20, 50]&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/rf_params.png&quot; alt=&quot;&quot; height=&quot;40%&quot; width=&quot;40%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://spark.apache.org/docs/latest/mllib-ensembles.html#gradient-boosted-trees-gbts&quot;&gt;Gradient-Boosted Trees&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;maxDepth&lt;/strong&gt; Maximum Tree Depth, default=5: &lt;strong&gt;[5, 7]&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;maxIter&lt;/strong&gt; Maximum number of iterations, default=20: &lt;strong&gt;[70, 100]&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/gbt_params.png&quot; alt=&quot;&quot; height=&quot;40%&quot; width=&quot;40%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;trained-models-evaluation&quot;&gt;Trained Models Evaluation&lt;/h3&gt;

&lt;p&gt;After the hyperparameter tuning the models were re-trained with the the best performing parameters and evaluated using the F1 Score and AUC metric.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-08-04/models_evaluation.png&quot; alt=&quot;&quot; height=&quot;80%&quot; width=&quot;80%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Gradient Boosted Tree turned to be the winning model predicting how likely is a user to churn.&lt;/p&gt;

&lt;p&gt;We have to emphasize that the results correspond to models that were trained and tested using a small data-set. The data-set sample contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;286500&lt;/code&gt; events logs for only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;225&lt;/code&gt; unique users.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Let’s take a step back and look at the whole journey.&lt;/p&gt;

&lt;p&gt;We wanted to predict customers churn for a hypothetical music streaming service. That using Apache Spark in all the Machine Learning workflow steps. For that we needed to have a binary classifier for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Churner&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Engaged&lt;/code&gt; customers.&lt;/p&gt;

&lt;p&gt;I started by performing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data cleaning&lt;/code&gt; to remove log events without a user Id and checked the missing vakues in the dataset. I then did multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data explorations&lt;/code&gt; to see how various indicators can help in distinguishing between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Churned&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Engaged&lt;/code&gt; customers. I defined the customer churn indicator based on wether the user visited the any of the pages &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cancellation Confirmation&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Downgrade Submission&lt;/code&gt; or not. Next in the features engineering step I extracted categorical and numerical features. For that I used the observed indicators during the data exploration. I also explored the last 20 days of service usage to represent the behaviour of the user before the churn event based on the number of sessions and the number of songs each day.
We split the data into training and validation data sets. And as a final step I performed model training by trying out various models varying from simple to complex ones: Logistic Regression, Random Forest and Gradient-Boosted Trees. I leveraged cross validation and grid search to fine tune the different models. Their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;performance&lt;/code&gt; got compared using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AUC&lt;/code&gt; metric.&lt;/p&gt;

&lt;p&gt;Gradient-Boosted Trees turned to be the winning model. We achieved about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.64&lt;/code&gt; AUC, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.59&lt;/code&gt; F1 Score. Potentially with the whole dataset, the data exploration observation and features engineering will be more informative and stable. The model might also be enhanced.&lt;/p&gt;

&lt;h3 id=&quot;potential-improvements&quot;&gt;Potential Improvements&lt;/h3&gt;

&lt;p&gt;We Could try other models algorithms. But before that we would like to do more substantial data exploration and features engineering to have a more accurate model in detecting whether a user is likely to churn or not. For that we would:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add more temporal features reflecting the service usage over the last N days.&lt;/li&gt;
  &lt;li&gt;Optimize the data analysis and feature engineering steps applying more Spark best practices for having efficient data exploration as well as model training and testing processes.&lt;/li&gt;
  &lt;li&gt;Perform data exploration on bigger batches of data subsets before using the big dataset due to the substential statistical differences with the big dataset.&lt;/li&gt;
  &lt;li&gt;With a higher computations power, performing a better Hyperparameter tuning for other model algorithms on Spark Cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project code can be found &lt;a href=&quot;https://github.com/slitayem/sparkify_dsnd&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;further-reading-about-customer-churn&quot;&gt;Further reading about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Customer Churn&lt;/code&gt;&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.hubspot.com/service/customer-retention-metrics&quot;&gt;Customer Churn Metrics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.forentrepreneurs.com/customer-success/&quot;&gt;Managing Customer Success to Reduce Churn&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://neilpatel.com/blog/never-losing-saas-customers/&quot;&gt;8 Advanced Tips for Never Losing SaaS Customers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://baremetrics.com/academy/churn-prediction-can-improve-business&quot;&gt;How Churn Prediction Can Improve Your Business&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				
				<pubDate>Tue, 04 Aug 2020 00:00:00 +0000</pubDate>
				<link>/blog/2020/08/04/churn-prediction</link>
				<guid isPermaLink="true">/blog/2020/08/04/churn-prediction</guid>
			</item>
		
			<item>
				<title>How do developers perceive the OSS quality and how often do they contribute?</title>
				
				
					<description>&lt;!-- ![](https://cdn.sstatic.net/Sites/stackoverflow/company/Img/logos/so/so-logo.png?v=9c558ec15d8a){:height=&quot;50%&quot; width=&quot;50%&quot;} --&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/open-source-software.png&quot; alt=&quot;oss&quot; height=&quot;85%&quot; width=&quot;85%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Several studies &lt;a class=&quot;citation&quot; href=&quot;#Finnegan2007HowPO&quot;&gt;(Finnegan &amp;amp; Morgan, 2007)&lt;/a&gt; &lt;a class=&quot;citation&quot; href=&quot;#bianco2010&quot;&gt;(del Bianco et al., 2010)&lt;/a&gt; &lt;a class=&quot;citation&quot; href=&quot;#Lenarduzzi2019&quot;&gt;(Lenarduzzi et al., 2019)&lt;/a&gt; &lt;a class=&quot;citation&quot; href=&quot;#Lenarduzzi2020&quot;&gt;(Lenarduzzi et al., 2020)&lt;/a&gt; have shown that the motivations to adopt OSS have changed over time towards a better perception of it. OSS has been experiencing an &lt;a href=&quot;https://techcrunch.com/2019/01/12/how-open-source-software-took-over-the-world/&quot;&gt;increasing&lt;/a&gt; interest particularly in &lt;a href=&quot;https://techcrunch.com/2019/01/12/how-open-source-software-took-over-the-world/&quot;&gt;industry&lt;/a&gt;. This can be seen by &lt;a href=&quot;https://www.lightreading.com/enterprise-cloud/digital-transformation/how-microsoft-became-an-unlikely-open-source-champion/a/d-id/740691&quot;&gt;Microsoft&apos;s position&lt;/a&gt; change on OSS development over the past two decades.&lt;/p&gt;

&lt;p&gt;Since 10 years stackoverflow have been publishing annual &lt;a href=&quot;https://insights.stackoverflow.com/survey/&quot;&gt;Developer Survey&lt;/a&gt; results always showing insightful key results. Digging deeper into the survey from 2019 let us know more about the Open Source Software (OSS) contributions as well as the developers perception of OSS quality.&lt;/p&gt;

&lt;p&gt;We will answer to the following questions from the survey data:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#contrib_freq&quot;&gt;How often do developers contribute to OSS?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#hobbyist_dev&quot;&gt;Do Hobyist developers contribute more often to OSS?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#oss_quality_bias&quot;&gt;Does OSS quality perception play a bias role towards OSS contribution?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#experience&quot;&gt;Are experienced developers contributing more frequently to OSS?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#salary&quot;&gt;Do developers contributing to the OSS have a higher income?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The analysis notebook is available &lt;a href=&quot;https://github.com/slitayem/stackoverflow_survey_analysis&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start with a quick overview of the data.
We see that most of the survey respondents are from the USA.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/top15_countries.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;More than 80% of the respondents are developers.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/developer_type.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Most of the respondents are preceiving the OSS quality the same as or even of HIGHER quality than the closed source software.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/oss_perception_respondents.png&quot; alt=&quot;&quot; height=&quot;80%&quot; width=&quot;80%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;contrib_freq&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-often-do-developers-contribute-to-oss&quot;&gt;How often do developers contribute to OSS?&lt;/h2&gt;
&lt;p&gt;36.3 % of the developers have never contributed to Open Source Software while 63.6 % contribute to the OSS. But we see that only only 12.4% contribute once a month or more often.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/oss_contribution_frequency.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;hobbyist_dev&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;do-hobyist-developers-contribute-more-often-to-oss&quot;&gt;Do Hobyist developers contribute more often to OSS?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/hobbyist_oss_contribution.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The analysis shows that the hobbyist developers contribute more often to the OSS than non hobbyist ones. But among the survey respondents 23K hobbyists (32% of the hobbyists) have never contributed to the OSS.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;oss_quality_bias&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;does-oss-quality-perception-play-a-bias-role-towards-oss-contribution&quot;&gt;Does OSS quality perception play a bias role towards OSS contribution?&lt;/h2&gt;
&lt;p&gt;What if a bad OSS quality perception happens to be a blocker for OSS contribution. The respondents are then separated in two groups (hobbyists or not hobbyists). Then, respondents are grouped by the way they are perceiving OSS quality in addtion to the frequency of contribution to OSS.
The data analysis shows that developers contributing the least to OSS are the ones who are perceiving OSS as on average of lower quality than proprietary software and not developing as a hobby.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/oss_quality_perception.png&quot; alt=&quot;&quot; height=&quot;90%&quot; width=&quot;90%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;experience&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;are-experienced-developers-contributing-more-frequently-to-oss&quot;&gt;Are experienced developers contributing more frequently to OSS?&lt;/h2&gt;
&lt;p&gt;In the figure below, I was interested in checking the seniority level of developers contributing to OSS. For that, the survey respondents are grouped by years of experience ranges.&lt;/p&gt;

&lt;p&gt;We notice that the more years of experiences developers gain the less they contribute to OSS.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/oss_experience_years_groups.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;salary&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;do-developers-contributing-to-the-oss-have-a-higher-income&quot;&gt;Do developers contributing to the OSS have a higher income?&lt;/h2&gt;
&lt;p&gt;The respondents salary data shows significant skewness and kurtosis.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Kurtosis 18551.71
Skew 136
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The salary distribution appears to be right-tailed. For a better interpretation of the data I removed the outliers massively skewing it. Then, only salaries less than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20 * salary median&lt;/code&gt; are kept. The figure below shows the salary distribution after outliers removal from the data.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/salary_distribution.png&quot; alt=&quot;&quot; height=&quot;70%&quot; width=&quot;70%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The mean salary appears to be higher for respondents who are contributing more often for the OSS. The reason for that might be because developers are acquiring more experience and seniority not only by the number of years in working experience but also while contributing to more projects and learning from the OSS community. Much Open Source work is volunteered. But for some developers especially when contributions require significant time, &lt;a href=&quot;https://opensource.guide/getting-paid/&quot;&gt;getting paid&lt;/a&gt; to contribute to OSS is the only way they can participate. That might also be a reason for which OSS contributors are earning more than others.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/blog/2020-06-14/opensourcers_av_salary.png&quot; alt=&quot;&quot; height=&quot;60%&quot; width=&quot;60%&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this article, we took a look at the OSS contribution of developers according to Stack Overflow 2019 survey data. We checked developers perception of the OSS as well as wether they code as a hobby or not. That showed that developers coding as a hobby and having a good perception of OSS are more likely to contribute to OSS. Finally, we looked at the mean salary for each frequency of contribution group. We found that those who contributing more often to the OSS are more likely to earn a higher salary. The findings here are observational, not the result of a formal study.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ol class=&quot;bibliography&quot;&gt;&lt;li&gt;&lt;span id=&quot;Finnegan2007HowPO&quot;&gt;Finnegan, P., &amp;amp; Morgan, L. (2007). How Perceptions of Open Source Software Influence Adoption: An Exploratory Study. &lt;i&gt;ECIS&lt;/i&gt;.&lt;/span&gt;



&lt;!-- &lt;pre&gt;@inproceedings{Finnegan2007HowPO,
  title = {How Perceptions of Open Source Software Influence Adoption: An Exploratory Study},
  author = {Finnegan, Patrick and Morgan, Lorraine},
  booktitle = {ECIS},
  year = {2007}
}
&lt;/pre&gt; --&gt;&lt;/li&gt;
&lt;li&gt;&lt;span id=&quot;bianco2010&quot;&gt;del Bianco, V., Lavazza, L., Morasca, S., Taibi, D., &amp;amp; Tosi, D. (2010). &lt;i&gt;An Investigation of the Users’ Perception of OSS Quality&lt;/i&gt;. &lt;i&gt;319&lt;/i&gt;, 15–28. https://doi.org/10.1007/978-3-642-13244-5_2&lt;/span&gt;



&lt;!-- &lt;pre&gt;@inproceedings{bianco2010,
  author = {del Bianco, Vieri and Lavazza, Luigi and Morasca, Sandro and Taibi, Davide and Tosi, Davide},
  year = {2010},
  month = may,
  pages = {15-28},
  title = {An Investigation of the Users&apos; Perception of OSS Quality},
  volume = {319},
  doi = {10.1007/978-3-642-13244-5_2}
}
&lt;/pre&gt; --&gt;&lt;/li&gt;
&lt;li&gt;&lt;span id=&quot;Lenarduzzi2019&quot;&gt;Lenarduzzi, V., Tosi, D., Lavazza, L., &amp;amp; Morasca, S. (2019, May). &lt;i&gt;Why Do Developers Adopt Open Source Software? Past, Present and Future&lt;/i&gt;.&lt;/span&gt;



&lt;!-- &lt;pre&gt;@inproceedings{Lenarduzzi2019,
  author = {Lenarduzzi, Valentina and Tosi, Davide and Lavazza, Luigi and Morasca, Sandro},
  year = {2019},
  month = may,
  pages = {},
  title = {Why Do Developers Adopt Open Source Software? Past, Present and Future}
}
&lt;/pre&gt; --&gt;&lt;/li&gt;
&lt;li&gt;&lt;span id=&quot;Lenarduzzi2020&quot;&gt;Lenarduzzi, V., Taibi, D., Tosi, D., Lavazza, L., &amp;amp; Morasca, S. (2020, June). &lt;i&gt;Open Source Software Evaluation, Selection, and Adoption: a Systematic Literature Review&lt;/i&gt;.&lt;/span&gt;



&lt;!-- &lt;pre&gt;@inproceedings{Lenarduzzi2020,
  author = {Lenarduzzi, Valentina and Taibi, Davide and Tosi, Davide and Lavazza, Luigi and Morasca, Sandro},
  year = {2020},
  month = jun,
  pages = {},
  title = {Open Source Software Evaluation, Selection, and Adoption: a Systematic Literature Review}
}
&lt;/pre&gt; --&gt;&lt;/li&gt;&lt;/ol&gt;

</description>
				
				<pubDate>Sun, 14 Jun 2020 00:00:00 +0000</pubDate>
				<link>/blog/2020/06/14/oss-contrib-analysis</link>
				<guid isPermaLink="true">/blog/2020/06/14/oss-contrib-analysis</guid>
			</item>
		
	</channel>
</rss>