<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Monirah abdulaziz on Medium]]></title>
        <description><![CDATA[Stories by Monirah abdulaziz on Medium]]></description>
        <link>https://medium.com/@monirah-abdulaziz?source=rss-cac8f1becf29------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*3FwdplCsFYCwWBfY</url>
            <title>Stories by Monirah abdulaziz on Medium</title>
            <link>https://medium.com/@monirah-abdulaziz?source=rss-cac8f1becf29------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 00:18:28 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@monirah-abdulaziz/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Udacity Data Visualization Nanodegree Capstone Project]]></title>
            <link>https://monirah-abdulaziz.medium.com/udacity-data-visualization-nanodegree-capstone-project-eb4abf54d7db?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/eb4abf54d7db</guid>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Sun, 27 Jun 2021 15:32:11 GMT</pubDate>
            <atom:updated>2021-06-27T15:32:11.566Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*YNV2XduajMT0b7Zvex2KZQ.jpeg" /><figcaption><a href="https://vulcanotec.com/en/news/cereal-is-the-breakfast-food-of-our-childhoods-and-yes-of-our-future/">https://vulcanotec.com/en/news/cereal-is-the-breakfast-food-of-our-childhoods-and-yes-of-our-future/</a></figcaption></figure><p>This story is the capstone project of Udacity Data Visualization Nanodegree. Its main goal is to describe how I’ve improved an existing data visualization from Makeover Monday by combining what I’ve learned throughout the program.</p><h3>Step 1: Scope the Project and Gather Data</h3><p>Consequently, the first task was to choose an existing dataset. As I was always very interested in economic fields, so I checked datasets used for MakeoverMonday data then I chosen the Personal Consumption Expenditures on Food and beverages purchased for off-premises consumption.</p><p>The original data visualization is <a href="https://media.data.world/vAqrQGOzSyCUh6nC7870_Screenshot%202021-03-21%20at%201.30.54%20pm.png">here</a>; the dataset with all background information and data dictionary is <a href="https://apps.bea.gov/iTable/iTable.cfm?ReqID=19&amp;step=2#reqid=19&amp;step=2&amp;isuri=1&amp;1921=underlying">here</a>.</p><h3>Step 2: Explore and Assess the Data</h3><p>The main variable/categories in the original dataset are:</p><ul><li>Alcoholic beverages</li><li>Cereals and bakery products</li><li>Fats and oils</li><li>Coffee, tea, and other beverage materials</li><li>Fish and seafood</li><li>Fresh fruits and vegetables</li><li>Meats and poultry</li><li>Sugar and sweets</li><li>Milk, dairy products, and eggs</li><li>Mineral waters, soft drinks, and vegetable juices</li><li>Processed fruits and vegetables</li></ul><p>Under these main categories, there are many sub-categories:</p><ul><li>Beer</li><li>Spirits</li><li>Wine</li><li>Bakery products</li><li>Cereals</li><li>Fats and oils</li><li>Fish and seafood</li><li>Fruit (fresh)</li><li>Vegetables (fresh)</li><li>Beef and veal</li><li>Other meats</li><li>Pork</li><li>Poultry</li><li>Eggs</li><li>Fresh milk</li><li>Processed dairy products</li><li>Processed fruits and vegetables</li><li>Sugar and sweets</li><li>Coffee, tea, and other beverage materials</li><li>Mineral waters, soft drinks, and vegetable juices</li></ul><p>So we have 14901 combinations of all these parameters. Each of them is the dataset record that can be interpreted as follows: In January 1959 there are 3457 million dollars consumed on beer which is part of Alcoholic beverages.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aeYZcCcWERqte0PLtlU4-w.png" /></figure><p>The main goal of this step is to identify any limitations and biases in data collection, processing, and insights.</p><p><strong>What is well with the initial visualization?</strong></p><ol><li>Data source is mentioned</li><li>The title is simple and clear so that everyone can understand</li></ol><p><strong>What could be improved with the initial visualization?</strong></p><ol><li>Compare the cereal with other categories.</li><li>Expenditures per category over years.</li><li>Expenditures per category in covid 19 period.</li></ol><p><strong>Pre-processing done on household income dataset:</strong></p><ol><li>Downloaded datset (Excel file) <a href="https://data.world/makeovermonday/2021w12/workspace/file?filename=Personal+Consumption+Expenditures.xlsxhttps://data.world/makeovermonday/2021w12/workspace/file?filename=Personal+Consumption+Expenditures.xlsx">here</a>.</li><li>Created Tableau file</li><li>create many sheets as follow:</li></ol><p>a) Growth Rate to compare the cereal Vs other categories <a href="https://public.tableau.com/app/profile/monirah.abdulaziz/viz/cerealInCovid19g/overall">here</a></p><p>b) Growth Rate to compare the cereal Vs other categories by shown that the difference in millions of dolras. <a href="https://public.tableau.com/app/profile/monirah.abdulaziz/viz/cerealInCovid19g1/growthrate1">here</a></p><p>c) Pie char illustrate the expenditures per category in covid 19 period. <a href="https://public.tableau.com/app/profile/monirah.abdulaziz/viz/cerealInCovid19Piechart/PieChart">here</a></p><p>d) dashboard the combine the charts. <a href="https://public.tableau.com/app/profile/monirah.abdulaziz/viz/cerealInCovid19/dashboard">here</a></p><p>Thank you for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eb4abf54d7db" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building Movie Recommendation System with Surprise and python.]]></title>
            <link>https://monirah-abdulaziz.medium.com/building-movie-recommendation-system-with-surprise-and-python-e905de755c61?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/e905de755c61</guid>
            <category><![CDATA[collaborative-filtering]]></category>
            <category><![CDATA[surprise]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[movie-recommendation]]></category>
            <category><![CDATA[recommendations]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Thu, 04 Mar 2021 10:16:37 GMT</pubDate>
            <atom:updated>2021-03-04T10:16:37.784Z</atom:updated>
            <content:encoded><![CDATA[<p>Done by: <a href="https://medium.com/u/cac8f1becf29">Monirah</a>, <a href="https://medium.com/u/20e1553c7e2c">Aisha Y Hakami</a>, <a href="https://medium.com/u/87f03ec137ee">Lamalharbi</a> and <a href="https://medium.com/u/c026f26badf6">Mohammed Alali</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*P5LT-1q7A44eoJTV" /><figcaption>source: shorturl.at/fltG7</figcaption></figure><h3>Problem Identification</h3><p>Developing a recommender system for IPTV in Jawwy service provided by STC. Python and JupyterLab are tools with Sklearn libraries for implementing the proposed recommender system. The aim is to create a business value for a local company to improve their service, and STC was selected for this project with their service Jawwy since they shared its data in the open data initiative.</p><h4>In this blog, we will build a recommendation model by using the Surprise method</h4><p><strong>Surprise</strong> is a Python scikit for building and analyzing recommender systems that deal with explicit rating data.</p><h4>Surprise was designed with the following purposes in mind:</h4><ul><li>Give users perfect control over their experiments</li><li>Provide various ready-to-use prediction algorithms such as baseline algorithms, neighborhood methods</li><li>Make it easy to implement new algorithm ideas.</li><li>Provide tools to evaluate, analyze and compare the algorithms’ performance. Cross-validation procedures can be run very easily using powerful CV iterators (inspired by sci-kit-learn excellent tools.</li></ul><p>We’ll be working with the <a href="http://www2.informatik.uni-freiburg.de/~cziegler/BX/">j</a>awwy IPTV dataset to develop recommendation system algorithms, with the <a href="http://surpriselib.com/">Surprise library</a>, which was built by <a href="http://nicolas-hug.com/">Nicolas Hug</a>. Let’s dive in!</p><h3>Dataset</h3><p>Saudi operator STC launched an interactive IPTV service called InVision for its DSL customers to coincide with the start of Ramadan. The service is initially available in the three major cities Riyadh, Jeddah, and Dammam free of charge throughout the month of Ramadan. InVision provides free TV channels and pay-TV packages, time-shifting of programs, program recording, a video-on-demand library of religious and documentary programs, and a catch-up TV service to watch programs broadcast over the last seven days. In addition, users have access to a control panel to select programs and movies.</p><p>We admire STC&#39;s role in order to enable the data community, when STC launched Open Data initiative which can help in preparing a technical-aware Saudi generation in line with Vision 2030, by supporting researchers interested in Data Science, through enabling them to explore and process data through application and practice.</p><p>The data consist of 29,487 user behavior within 8k shows all in 3m row. we extract the juice out of all the behavioral patterns of not only the users but also from the movies themselves.</p><h3>Modeling</h3><p>In previous posts, we discuss two of the most popular ways to approach recommender systems are <a href="https://en.wikipedia.org/wiki/Collaborative_filtering">collaborative filtering</a> and <a href="https://www.analyticsvidhya.com/blog/2015/08/beginners-guide-learn-content-based-recommender-systems/">content-based recommendations</a>. In this blog, we will focus on the collaborative filtering approach, that is: the user is recommended items that people with similar tastes and preferences liked in the past. In another word, this method predicts unknown ratings by using the similarities between users.</p><h4>Surprise Model</h4><p><em>Surprise</em> provides a collection of estimators for rating prediction, classical algorithms are implemented such as the main similarity-based algorithms, as well as algorithms based on matrix factorization like SVD or NMF. It also supports tools for model evaluation like cross-validation iterators and built-in metrics.</p><p>Since <strong>surprise</strong> does not support implicit <strong>ratings</strong>, and our dataset hasn’t this important data as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*03qdj72KtpOLoLBUXU3J8g.png" /><figcaption>The head of the dataframe.</figcaption></figure><p>So we did some feature engineering to obtain the rating of watching for each user/movie, the idea is to consider the watching ratio as a rating.</p><p>The problem is the difference between movie and series in this dataset, the total movie duration is as the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NwKjvefL4T1W-DKaRus3Sg.png" /><figcaption>sample of movie</figcaption></figure><p>While the series is like the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6k76D3Vx-4E0WtgVVCI2ug.png" /><figcaption>sample of series</figcaption></figure><p>for movie programs, it is easy to obtain the ratio of watching and deal with it as a user rating, by using regex remove (min) word that suffix the number of minutes in duration feature which is the total duration for each movie from IMDB, then transform the time from minutes to seconds, after that divide the duration by the duration_second which is the duration of the user watching for this particular movie.</p><p>Unfortunately, we cannot apply these steps for series/ tv shows because the duration is for the season rather than the total duration of the episode of the series, and when we try to obtain this data from an external dataset, we face other problems which are some series/ tv shows will be lost, also there are many different movies have the same name like <a href="https://www.imdb.com/title/tt3281548/">little women</a> and <a href="https://www.imdb.com/title/tt0110367/">little women</a>.</p><p>So we split the dataset into 2 dataframe, the first one <em>merged_df_series</em> for TV Show and the second one <em>merged_df_movie</em> for Movie programs</p><p>for for TV Show programs to assign the total duration, we use .max() that returns the maximum of the values over the duration_seconds by users for each program/Tv Show as a total duration, since we don&#39;t have the total duration the dataset</p><pre>df_series_duration=merged_df_series.groupby(‘program_name’)[[‘duration_seconds’]].max()</pre><p>Add average_watching and total_duration, we will use it as a target for the surprise model.</p><pre>#average_watching<br>merged_df_series[“average_watching”] = merged_df_series.apply(lambda x: 1 if x[‘duration_seconds’] &gt; df_series_duration.loc[x.program_name,’duration_seconds’] else x[‘duration_seconds’]/df_series_duration.loc[x.program_name,’duration_seconds’], axis=1)</pre><pre># total_duration <br>merged_df_series[“total_duration”]= merged_df_series.apply(lambda x: df_series_duration.loc[x.program_name,’duration_seconds’],axis=1)</pre><h4>The head of the series dataset:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GKbBEdq9YsUwNztIbxIOVw.png" /></figure><p>Remember that the average watching represents the ratio of watching for each user for a particular program.</p><p>For Movie programs:</p><pre># Extract minute by using (regex) and convert to appropriate type <br>merged_df_movie[‘total_duration’] = merged_df_movie[‘duration’].str.replace(r’min’, ‘’)<br>merged_df_movie[‘duration_seconds’] = pd.to_numeric((merged_df_movie[‘duration_seconds’]) , errors=’coerce’).astype(‘Int64’)<br>merged_df_movie[‘total_duration’] = pd.to_numeric((merged_df_movie[‘total_duration’]) , errors=’coerce’).astype(‘Int64’)</pre><pre># convert from min to sec<br>merged_df_movie[‘total_duration’]=(merged_df_movie[‘total_duration’]*60)</pre><p>IF the value of duration_seconds &gt; total_duration, assign the value of total_duration to duration_seconds:</p><pre>merged_df_movie[“duration_seconds”] = merged_df_movie.apply(lambda x: x[‘total_duration’] if x[‘duration_seconds’] &gt; x[‘total_duration’] else x[‘duration_seconds’], axis=1)</pre><p>Add average_watching Feature, we will use it as a target for the surprise model.</p><pre>merged_df_movie[‘average_watching’]=merged_df_movie[‘duration_seconds’]/merged_df_movie[‘total_duration’]</pre><h4>The head of the movies dataset:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*seOGJe8H0UvnqPJfa45zYg.png" /></figure><h3>Concatenate Dataframes</h3><ul><li>concatenate merged_df_movie and merged_df_series and check outliers.</li></ul><p>The dataset looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EceQaxlUb2jfERj4MxVeLA.png" /><figcaption>Sample of the merged dataset</figcaption></figure><p>Some EDA:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WLcTRyHG1xSQu1iPvFiq5w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/305/1*HJjA7-jhH0uOQ9PVz_rjKg.png" /><figcaption>most-watched program</figcaption></figure><p>Most of the programs in the data watched less than 3 times, and very few programs have many watching, although the most-watched program has been watched 2312 times</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2XxUUrwgUO73t6hxdsVkSQ.png" /><figcaption>Distribution Of Number of Watching Per User</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/322/1*4jaMNwWfqJmV0svxjtPYhw.png" /><figcaption>most-active users</figcaption></figure><p>Most of the users in the data had less than 10 watched programs, and not many users had many watchings, although the most-active user has been watched 136 programs.</p><pre>reader = Reader(rating_scale=(0.03, 1.0))<br>data = Dataset.load_from_df(df_data[[‘user_id’, ‘show_id’, ‘average_watching’]], reader)</pre><pre>benchmark = []<br># Iterate over all algorithms<br>for algorithm in [SVD(), SVDpp(), SlopeOne(), NMF(), NormalPredictor(), KNNBaseline(), KNNBasic(),<br> KNNWithMeans(), KNNWithZScore(), BaselineOnly()]:<br> # Perform cross validation<br> results = cross_validate(algorithm, data, measures=[‘RMSE’], cv=3, verbose=False)<br> <br> # Get results &amp; append algorithm name<br> tmp = pd.DataFrame.from_dict(results).mean(axis=0)<br> tmp = tmp.append(pd.Series([str(algorithm).split(‘ ‘)[0].split(‘.’)[-1]], index=[‘Algorithm’]))<br> benchmark.append(tmp)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/446/1*RuS6B1umdwO2GTO42baAmw.png" /><figcaption>various algorithms and their scores</figcaption></figure><h3>Train and Predict</h3><p>BaselineOnly algorithm gave us the best rmse, therefore, we will train and predict with BaselineOnly and use Alternating Least Squares (ALS).</p><pre><br>print(‘Using ALS’)<br>bsl_options = {‘method’: ‘als’,<br> “random_state”:250,<br> ‘n_epochs’: 5,<br> ‘reg_u’: 12,<br> ‘reg_i’: 5<br> }<br>algo = BaselineOnly(bsl_options)<br>cross_validate(algo, data, measures=[‘RMSE’], cv=3, verbose=False)</pre><pre>Using ALS<br>Estimating biases using als...<br>Estimating biases using als...<br>Estimating biases using als...</pre><p>Out:</p><pre>{&#39;test_rmse&#39;: array([0.32846883, 0.32829109, 0.32849049]),<br> &#39;fit_time&#39;: (0.05880260467529297, 0.04584360122680664, 0.06278657913208008),<br> &#39;test_time&#39;: (0.1285717487335205, 0.14949917793273926, 0.12757420539855957)}</pre><p>We use the train_test_split() to sample a trainset and a test set with given sizes, and use the accuracy metric of rmse. We’ll then use the fit() the method which will train the algorithm on the trainset, and the test() the method which will return the predictions made from the testset.</p><pre>trainset, testset = train_test_split(data, test_size=0.25)<br>algo = BaselineOnly(bsl_options)<br>predictions = algo.fit(trainset).test(testset)<br>accuracy.rmse(predictions)</pre><p>Out:</p><pre>Estimating biases using als...<br>RMSE: 0.3295</pre><p>To inspect our predictions in detail, we are going to build a pandas data frame with all the predictions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/807/1*ve6Kqp5d1Zt9JdP0I0AAfw.png" /><figcaption>The predictions in detail</figcaption></figure><h4>User’s 13618 behavior</h4><ul><li>Here we will study the watching behavior for a particular user his ID is (13618)</li></ul><pre># user_id is the 13618<br>ratings = newdf.loc[newdf[‘user_id’] == 13618]<br># obtain the required data of this user<br>ratings=ratings[[‘user_id’, ‘show_id’, ‘average_watching’]]<br>ratings</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/395/1*Sihu_0d8F4UkPfLJXILGew.png" /></figure><pre># get the list of the movie ids<br>unique_ids = newdf[‘show_id’].unique()</pre><pre># get the list of the ids that the userid 13618 has watched<br>iids1001 = newdf.loc[newdf[‘user_id’]==13618, ‘show_id’]</pre><pre># remove the rated movies for the recommendations<br>movies_to_predict = np.setdiff1d(unique_ids,iids1001)</pre><h4>Recommendation Programs For User’s 13618</h4><pre>algo = BaselineOnly(bsl_options)<br>algo.fit(data.build_full_trainset())</pre><pre>my_recs = []<br>for iid in movies_to_predict:<br> my_recs.append((iid, algo.predict(uid=’13618&#39;,iid=iid).est))<br>pd.DataFrame(my_recs, columns=[‘iid’, ‘predictions’]).sort_values(‘predictions’, ascending=False).head(10)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/220/1*y6y6KbSzBLP0HAG4PJwTkg.png" /><figcaption>Prediction estimators</figcaption></figure><p>That was it! I hope you enjoyed the recommendation (or rather, a rating prediction) journey with <a href="https://surprise.readthedocs.io/en/stable/index.html">Surprise</a>.</p><p>Reference:</p><ul><li><a href="https://surprise.readthedocs.io/en/stable/index.html">Surprise’ documentation</a></li><li><a href="https://actsusanli.medium.com/">https://actsusanli.medium.com/</a></li><li><a href="https://predictivehacks.com/how-to-run-recommender-systems-in-python/">https://predictivehacks.com/how-to-run-recommender-systems-in-python/</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e905de755c61" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Movie Recommendation System]]></title>
            <link>https://monirah-abdulaziz.medium.com/movie-recommendation-system-8e4e15b84485?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/8e4e15b84485</guid>
            <category><![CDATA[hybrid]]></category>
            <category><![CDATA[content-based-filtering]]></category>
            <category><![CDATA[recommendation-system]]></category>
            <category><![CDATA[collaborative-filtering]]></category>
            <category><![CDATA[iptv]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Mon, 01 Mar 2021 19:16:46 GMT</pubDate>
            <atom:updated>2021-03-01T19:16:46.036Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This project was build by Neon team : </em><a href="https://medium.com/u/20e1553c7e2c"><em>Aisha Y Hakami</em></a>, <a href="https://medium.com/u/cac8f1becf29">Monirah abdulaziz</a>, <a href="https://www.linkedin.com/in/m-s-alali/">Mohammed Al-Ali</a>, and <a href="https://medium.com/u/87f03ec137ee">Lamalharbi</a>.</p><p>In our daily life when we are shopping online, or looking for a movie to watch, we usually ask the recommendation from our friends for their personal opinion, and when they recommend something that we don’t like but they enjoyed it, what a waste of time right !!. So if there is a system that can understand you, and recommend for you based on your interests, that would be soo cool isn’t it. Well, that precisely what recommender systems are made for.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FWPib4KPq3sE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DWPib4KPq3sE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWPib4KPq3sE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6cca1756cbfad8eb1d381c15d617aa3/href">https://medium.com/media/d6cca1756cbfad8eb1d381c15d617aa3/href</a></iframe><h3>Problem Statement</h3><p>Coming to the streaming shows websites, understanding the user’s behavior always consider a challenge. Irrespective of gender, age, or geographical location everyone enjoying watching movies at home. Bunch of people like genre-specific movies to be romance, action, or comedy while others enjoying the lead actors and directors’ visions. We all are connected via this wonderful medium. However, what most exciting is the fact that how distinctive our choices and combinations are in terms of the show’s preferences. But, when we take all that has been said, it’s remarkably difficult to generalize a movie and say that everyone would like it. So here the recommender systems shine to act as special assistants for the user’s needs.</p><h3>Dataset</h3><p>We found out that <a href="https://www.stc.com.sa/wps/wcm/connect/english/individual/campaign/bigdata?utm_source=twitter&amp;utm_campaign=open_data_day&amp;utm_medium=tweet&amp;utm_content=arabic">STC</a> launched an Open Data initiative to support those who are interested in Data Science, the data is associated with Jawwy, which is their IPTV service. And we decided that this will be the beginning of the neon recommendation system journey. The data consist of 29,487 user behavior within 8k shows all in 3m row. we extract the juice out of all the behavioral patterns of not only the users but also from the movies themselves.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/891/1*Dnj7Xyygq52GamNuS_WayA.png" /></figure><h3>Modeling</h3><p>We decided that we want to use 6 models to meet user preferences as much as we can those models are :</p><h4>Collaborative filtering</h4><p>This type of filter is based on users’ watching history, and it will recommend us movies that we haven’t watched yet, but users similar to us have and like. To determine whether two users are similar or not, this filter considers the movies both of them watched. By looking at the movies in common, this type of algorithm will basically recommend the movie for a user who hasn’t watched it yet, based on the similar users’ watching history.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/0*J4rHK4G52mhoiMdZ.png" /><figcaption>Collaborative filtering</figcaption></figure><h4><em>Pros and Cons of collaborative filtering technique</em></h4><h4>Pros:</h4><ol><li>Collaborative filtering systems work by people in the system, and it is expected that people to be better at evaluating information than a computed function.</li></ol><h4>Cons:</h4><ol><li>Cold Start: a major challenge of the Collaborative Filtering technique can be how to make recommendations for a new user who has recently entered the system; that is called the cold-start user problem.</li><li>Sparsity:</li></ol><ul><li>The user/rating matrix is sparse.</li><li>Hard to find users that have rated the same items.</li></ul><p>3. First rater:</p><ul><li>Cannot recommend an item that has not been previously rated.</li><li>New items, Esoteric items.</li></ul><p>4. Popularity bias:</p><ul><li>Cannot recommend items to someone with a unique taste.</li><li>Tends to recommend popular items.</li></ul><h4>Content-based filters</h4><p>Based on what we like, the algorithm will simply pick a movie with similar content(story description )to recommend us. This type of filter does not involve other users.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/247/0*u-_TevDgZhRxPWVA.png" /></figure><h4>Pros and Cons of content-based technique</h4><p>Pros :</p><ol><li>No cold-start problem, unlike Collaborative Filtering, if the programs have sufficient descriptions, we avoid the “new item problem”.</li><li>Able to recommend to users with unique tastes</li></ol><p>Cons :</p><ol><li>Content-Based tend to over-specialization: they will recommend items similar to those already consumed, with a tendency of creating a “filter bubble”.</li><li>Never recommends items outside the user’s content profile, people might have multiple interests.</li></ol><h4>Hybrid filtering :</h4><ul><li>Overcomes previous cons.</li><li>Create a weighted recommender (weights are chosen equally, combining the results of predict_cf and predict_cn).</li><li>Create differently weighted recommender (weights are chosen equally, combining the results of predict_cf, predict_cn, and predict_popularity)</li><li>Create recommender based on popularity with weighted CL and CB (which CL and CB predictions affected by popularity prediction)</li><li>Keep the strengths of CL, CB, and popularity models.</li><li>Overcomes CL, CB, and popularity models cons.</li></ul><pre>indices = pd.Series(df_program_desc.index)<br><em># defining the function that takes in movie title </em><br><em># as input and returns the top 10 recommended movies</em></pre><pre><strong>def</strong> recommendations(title,type_of_recommendation, cosine_sim = cosine_sim, cosine_sim_w = cosine_sim_w, prec_watch_mat = prec_watch_mat):<br> <em>‘’’</em><br><em> type_of_recommendation values:</em><br><em> </em><br><em> 0: the similarity scores of program description (Content Based),</em><br><em> 1: the similarity scores of watch history (Collaborative filtering),</em><br><em> 2: the similarity scores between watch history and program description (Hybrid),</em><br><em> 3: the similarity scores between watch history and program description </em><br><em> with popularity of program as indepent variables (Hybrid),</em><br><em> 4: the similarity scores between watch history and program description </em><br><em> as depent variables on popularity of program (Hybrid).</em><br><em> ‘’’</em><br> <br> <br> <em># initializing the empty list of recommended movies</em><br> recommended_movies = []<br> <br> <em># gettin the index of the movie that matches the title</em><br> idx = indices[indices == title].index[0]<br> <br> <strong>if</strong> type_of_recommendation == 0:<br> <br> <em># creating a Series with the similarity scores of program description in descending order</em><br> score_series = pd.Series(cosine_sim[idx]).sort_values(ascending = <strong>False</strong>)<br> <br> <strong>elif</strong> type_of_recommendation == 1:<br> <br> <em># creating a Series with the similarity scores of watch history in descending order</em><br> score_series = pd.Series(cosine_sim_w[idx]).sort_values(ascending = <strong>False</strong>)<br> <br> <strong>elif</strong> type_of_recommendation == 2:<br> <br> <em># creating a Series with the similarity scores between watch history and program description in descending order</em><br> score_series = pd.Series(cosine_sim_w[idx]*0.5 + cosine_sim[idx]*0.5).sort_values(ascending = <strong>False</strong>)<br> <strong>elif</strong> type_of_recommendation == 3:<br> <br> <em># creating a Series with the similarity scores between watch history and program description </em><br> <em># with popularity of program as indepent variables in descending order</em><br> score_series = pd.Series(cosine_sim_w[idx]*0.33 + cosine_sim[idx]*0.33 + prec_watch_mat*0.34).sort_values(ascending = <strong>False</strong>)<br> <strong>elif</strong> type_of_recommendation == 4:<br> <br> <em># creating a Series with the similarity scores between watch history and program description </em><br> <em># as depent variables on popularity of program in descending order</em><br> score_series = pd.Series((cosine_sim_w[idx]*0.5 + cosine_sim[idx]*0.5) * prec_watch_mat).sort_values(ascending = <strong>False</strong>)<br> <br> <strong>else</strong>:<br> print(‘You have entered wrong value’)<br> <strong>return<br></strong><em># getting the indexes of the 10 most similar movies</em><br> top_10_indexes = list(score_series.iloc[1:11].index)<br> <br> <em># populating the list with the titles of the best 10 matching movies</em><br> <strong>for</strong> i <strong>in</strong> top_10_indexes:<br> recommended_movies.append(list(df_program_desc.index)[i])<br> <br> <strong>return</strong> recommended_movies</pre><h3>How does Cosine Similarity work?</h3><p>All the filters above will be measured by <em>Cosine similarity</em> which is a metric used to measure how similar the documents are irrespective of their size. Mathematically, it measures the cosine of the angle between two vectors projected in a multi-dimensional space. The cosine similarity is advantageous because even if the two similar documents are far apart by the Euclidean distance (due to the size of the document), chances are they may still be oriented closer together. The smaller the angle, the higher the cosine similarity.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/0*-mwSdhUUZSeYWJBs.png" /><figcaption>cousin similarity</figcaption></figure><pre><em># instantiating and generating the count matrix</em><br>count = CountVectorizer()<br>count_matrix_desc = count.fit_transform(df_program_desc[‘cleaned_desc’])</pre><pre><em># generating the cosine similarity matrix on program description</em><br>cosine_sim = cosine_similarity(count_matrix_desc, count_matrix_desc)</pre><pre><em># generating the cosine similarity matrix on watch history</em><br>cosine_sim_w = cosine_similarity(watch_crosstab_transpose.values, watch_crosstab_transpose.values)</pre><p>Also, we use Surprise library that I am going to write an article in a near future.</p><h3>Demo</h3><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F6GwJTpa_wew%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D6GwJTpa_wew&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F6GwJTpa_wew%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/962955d3b1706704c2647c205e858eb2/href">https://medium.com/media/962955d3b1706704c2647c205e858eb2/href</a></iframe><h3>Result</h3><p>we used the Hit-Rate as an evaluation metric for the cosine matrix algorithms</p><p>The Hit-Rate Generate the top n recommendation for a user and compare them to those the user watched. If they match then increase the hit rate by 1, do this for the complete dataset to get the hit rate. Since we want to recommend movies that new to the user so the closest to 0 the better. We sum the number of hits for each movie in our top-N list and divide by the total number of movies.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/866/0*XIr3KufqAJJEZi2s.png" /><figcaption>result of hit rate matrics</figcaption></figure><p>Since we want to recommend movies that new to the user so the closest to 0 the better. The content-based model represents a good score, while the collaborative not that good. The hybrid model keeps the strength of the previous models and got a good score. the hybrid and popularity models are biased to user preferences and represent a not bad score as well.</p><p>Thank you for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8e4e15b84485" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[House Prices —Data Cleaning]]></title>
            <link>https://monirah-abdulaziz.medium.com/house-prices-data-cleaning-ec45bb960a1?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/ec45bb960a1</guid>
            <category><![CDATA[cleaning]]></category>
            <category><![CDATA[advanced-regression]]></category>
            <category><![CDATA[kaggle-competition]]></category>
            <category><![CDATA[mls]]></category>
            <category><![CDATA[house-prices]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Mon, 01 Mar 2021 18:21:54 GMT</pubDate>
            <atom:updated>2021-03-01T18:21:54.296Z</atom:updated>
            <content:encoded><![CDATA[<p>Done by: <a href="https://medium.com/u/cac8f1becf29">Monirah abdulaziz</a>, <a href="https://medium.com/u/87f03ec137ee">Lamalharbi</a>, and <a href="https://medium.com/u/20e1553c7e2c">Aisha Y Hakami</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SfaFQV6K3J_LJa_e.jpg" /><figcaption>source: shorturl.at/anA57</figcaption></figure><p>This article goes through the process of cleaning a dataset which consists of information about the location of the house, price, and other aspects such as square feet, etc. When we work on these sorts of data, we need to modify and aggregate some features to expand their importance and see which column is important for us and which is not. The main goal of this article is to prepare data to do modeling steps that can give us a good prediction on the price of the house based on the other variables.</p><h3>Data Dictionary</h3><ul><li>There are 81 features in this dataset,</li><li>This is the data dictionary of the dataset before cleaning steps:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8e7Blrz_q2O1Luv4SysUuw.png" /><figcaption>The head of the data dictionary</figcaption></figure><p>Check nulls:</p><pre>df.isnull().sum()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/467/1*6F-bkWG7rDfxc_3P7JgfOw.png" /><figcaption>Null values</figcaption></figure><h4>Handling Missing Values</h4><p>Divide the data into numerical (“quan”), and categorical (“qual”) features.</p><pre>quan = list( test.loc[:,test.dtypes != ‘object’].drop(‘Id’,axis=1).columns.values )<br>qual = list( test.loc[:,test.dtypes == ‘object’].columns.values )</pre><p>Find out how many missing values there are for the quantitative and categorical features</p><pre>print(&#39;Quantitative\n&#39;)<br>hasNAN = df[quan].isnull().sum()<br>hasNAN = hasNAN[hasNAN &gt; 0]<br>hasNAN = hasNAN.sort_values(ascending=False)<br>print(hasNAN)<br>print (&#39;-&#39; * 100)<br>print(&#39;Qualitative\n&#39;)<br>hasNAN = df[qual].isnull().sum()<br>hasNAN = hasNAN[hasNAN &gt; 0]<br>hasNAN = hasNAN.sort_values(ascending=False)<br>print(hasNAN)</pre><h4>The output is shown here:</h4><pre>Quantitative</pre><pre><br>LotFrontage     486<br>GarageYrBlt     159<br>MasVnrArea       23<br>BsmtHalfBath      2<br>BsmtFullBath      2<br>GarageArea        1<br>GarageCars        1<br>TotalBsmtSF       1<br>BsmtUnfSF         1<br>BsmtFinSF2        1<br>BsmtFinSF1        1<br>dtype: int64<br>----------------------------------------------------------------------------------------------------<br>Qualitative<br><br>PoolQC          2909<br>MiscFeature     2814<br>Alley           2721<br>Fence           2348<br>FireplaceQu     1420<br>GarageCond       159<br>GarageQual       159<br>GarageFinish     159<br>GarageType       157<br>BsmtExposure      82<br>BsmtCond          82<br>BsmtQual          81<br>BsmtFinType2      80<br>BsmtFinType1      79<br>MasVnrType        24<br>MSZoning           4<br>Functional         2<br>Utilities          2<br>Exterior1st        1<br>SaleType           1<br>Exterior2nd        1<br>KitchenQual        1<br>Electrical         1<br>dtype: int64</pre><p>Rather than the statistical computing methods to fill the missing values like mean, median, or mode, we prefer to do it manually, the benefit of this procedure is to get deep insight and understanding about the data, adding that make enhancements to some features in the feature engineering stage.</p><p>Remember the meaning of these features:</p><ul><li><strong>LotFrontage</strong>: Linear feet of street-connected to property</li><li><strong>LotShape</strong>: General shape of a property</li><li><strong>Neighborhood</strong>: Physical locations within Ames city limits</li></ul><pre>print(df[[‘LotShape’, ‘Neighborhood’,’LotFrontage’]].loc[df[‘LotFrontage’].isnull()])</pre><p>The output:</p><pre>LotShape Neighborhood  LotFrontage<br>7         IR1       NWAmes          NaN<br>12        IR2       Sawyer          NaN<br>14        IR1        NAmes          NaN<br>16        IR1        NAmes          NaN<br>24        IR1       Sawyer          NaN<br>...       ...          ...          ...<br>2847      Reg      CollgCr          NaN<br>2850      IR2      CollgCr          NaN<br>2900      IR1       Timber          NaN<br>2901      IR1       Timber          NaN<br>2908      IR1      Mitchel          NaN<br><br>[486 rows x 3 columns]</pre><h4>Filling missing values for numerical features.</h4><p>Most of the NAN should mean that The corresponding facility/structure doesn’t exist, so we use zero for most cases</p><pre>df.LotFrontage.fillna(df.LotFrontage.median(), inplace=True)<br>df[“LotFrontage”] = df[“LotFrontage”].fillna(df.groupby([“Neighborhood”, “LotShape”])[“LotFrontage”].transform(“median”))</pre><h4>NAN should mean no garage. we temporarily use yr = 0 here. Will come back to this later.</h4><pre>df.GarageYrBlt.fillna(0, inplace=True)</pre><h4>Use zero to fill following nulls</h4><pre>df.MasVnrArea.fillna(0, inplace=True) <br>df.BsmtHalfBath.fillna(0, inplace=True)<br>df.BsmtFullBath.fillna(0, inplace=True)<br>df.GarageArea.fillna(0, inplace=True)<br>df.GarageCars.fillna(0, inplace=True) <br>df.TotalBsmtSF.fillna(0, inplace=True) <br>df.BsmtUnfSF.fillna(0, inplace=True) <br>df.BsmtFinSF2.fillna(0, inplace=True) <br>df.BsmtFinSF1.fillna(0, inplace=True)<br>df.Electrical.fillna(df.Electrical.mode()[0], inplace=True)</pre><h4>Filling missing values for categorical features with not available (NA)</h4><pre>df.PoolQC.fillna(&#39;NA&#39;, inplace=True)<br>df.MiscFeature.fillna(&#39;NA&#39;, inplace=True)    <br>df.Alley.fillna(&#39;NA&#39;, inplace=True)          <br>df.Fence.fillna(&#39;NA&#39;, inplace=True)         <br>df.FireplaceQu.fillna(&#39;NA&#39;, inplace=True)    <br>df.GarageCond.fillna(&#39;NA&#39;, inplace=True)    <br>df.GarageQual.fillna(&#39;NA&#39;, inplace=True)     <br>df.GarageFinish.fillna(&#39;NA&#39;, inplace=True)   <br>df.GarageType.fillna(&#39;NA&#39;, inplace=True)     <br>df.BsmtExposure.fillna(&#39;NA&#39;, inplace=True)     <br>df.BsmtCond.fillna(&#39;NA&#39;, inplace=True)        <br>df.BsmtQual.fillna(&#39;NA&#39;, inplace=True)        <br>df.BsmtFinType2.fillna(&#39;NA&#39;, inplace=True)     <br>df.BsmtFinType1.fillna(&#39;NA&#39;, inplace=True)     <br>df.MasVnrType.fillna(&#39;None&#39;, inplace=True)   <br>df.Exterior2nd.fillna(&#39;None&#39;, inplace=True)</pre><pre>df.KitchenQual.fillna(&#39;NA&#39;, inplace=True)        <br>df.Exterior1st.fillna(&#39;NA&#39;, inplace=True)     <br>df.SaleType.fillna(&#39;NA&#39;, inplace=True)<br>df.Functional.fillna(&#39;NA&#39;, inplace=True)<br>df.Utilities.fillna(&#39;NA&#39;, inplace=True)</pre><h4>MSZoning should highly correlate with the location, so I use the mode values of individual Neighborhoods</h4><pre>for i in df.Neighborhood.unique():<br>    if df.MSZoning[df.Neighborhood == i].isnull().sum() &gt; 0:<br>        df.loc[df.Neighborhood == i,&#39;MSZoning&#39;] = \<br>        df.loc[df.Neighborhood == i,&#39;MSZoning&#39;].fillna(df.loc[df.Neighborhood == i,&#39;MSZoning&#39;].mode()[0])</pre><h4>Qualitative</h4><pre>fig = plt.subplots(nrows = 1, ncols = 1, figsize = (18, 6))<br>sns.heatmap(df[qual].isnull(), yticklabels=False, cbar=False, cmap=’viridis’)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dqXUNZuAPApB4NzihO2qFA.png" /><figcaption>heat map empty from nulls</figcaption></figure><h4>Check duplicate</h4><pre># Eliminating the duplicates.<br>df.duplicated(subset=None, keep=’first’).sum()</pre><pre>0</pre><h3>Feature Engineering</h3><p>If we use one-hot encoding we will get a huge number of features, to avoid that, we decide to combine features that have similar data meaning.</p><pre>df.Heating.value_counts()</pre><pre>GasA     2874<br>GasW       27<br>Grav        9<br>Wall        6<br>OthW        2<br>Floor       1<br>Name: Heating, dtype: int64</pre><p>So we will combine all values (Grav, Wall, OthW, and Floor 1) together since their values have appeared a few times.</p><pre>df[“Heating”] = df[“Heating”].apply(lambda x: “Other” if x != “GasA” else x)</pre><ul><li>MasVnrType</li></ul><pre>df.MasVnrType.value_counts()</pre><pre>None       1766<br>BrkFace     879<br>Stone       249<br>BrkCmn       25<br>Name: MasVnrType, dtype: int64</pre><p>So we will combine all values (Stone, BrkCmn ) to None since their values have appeared a few times.</p><pre>df[“MasVnrType”] = df[“MasVnrType”].apply(lambda x: “None” if x in [“None”, “BrkCmn”] else x)</pre><p>And do the same steps for all categorical features.</p><h4>Converting categorical variables into labels:</h4><pre>df.Alley = df.Alley.map({‘NA’:0, ‘Grvl’:1, ‘Pave’:2})<br>df.BsmtCond = df.BsmtCond.map({‘NA’:0, ‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.BsmtExposure = df.BsmtExposure.map({‘NA’:0, ‘No’:1, ‘Mn’:2, ‘Av’:3, ‘Gd’:4})<br>df[‘BsmtFinType1’] = df[‘BsmtFinType1’].map({‘NA’:0, ‘Unf’:1, ‘LwQ’:2, ‘Rec’:3, ‘BLQ’:4, ‘ALQ’:5, ‘GLQ’:6})<br>df[‘BsmtFinType2’] = df[‘BsmtFinType2’].map({‘NA’:0, ‘Unf’:1, ‘LwQ’:2, ‘Rec’:3, ‘BLQ’:4, ‘ALQ’:5, ‘GLQ’:6})<br>df.BsmtQual = df.BsmtQual.map({‘NA’:0, ‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.ExterCond = df.ExterCond.map({‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.ExterQual = df.ExterQual.map({‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.FireplaceQu = df.FireplaceQu.map({‘NA’:0, ‘TA’:1, ‘Gd’:2, ‘other’:3})<br>df.Functional = df.Functional.map({ ‘Min1’:2, ‘Typ’:1})<br>df.GarageCond = df.GarageCond.map({‘NA’:0, ‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.GarageQual = df.GarageQual.map({‘NA’:0, ‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.HeatingQC = df.HeatingQC.map({‘Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.KitchenQual = df.KitchenQual.map({‘NA’:0,’Po’:1, ‘Fa’:2, ‘TA’:3, ‘Gd’:4, ‘Ex’:5})<br>df.LandSlope = df.LandSlope.map({‘Sev’:1, ‘Mod’:2, ‘Gtl’:3}) <br>df.PavedDrive = df.PavedDrive.map({‘N’:1, ‘P’:2, ‘Y’:3})<br>df.PoolQC = df.PoolQC.map({‘NA’:0,’Ex’:1})<br>df.Street = df.Street.map({‘Grvl’:1, ‘Pave’:2})<br>df.Utilities = df.Utilities.map({‘NA’:0,’ELO’:1, ‘NoSeWa’:2, ‘NoSewr’:3, ‘AllPub’:4})</pre><p>Update the lists of numerical and categorical features:</p><pre>newquan = [‘Alley’,’BsmtCond’,’BsmtExposure’,’BsmtFinType1&#39;,’BsmtFinType2&#39;,’BsmtQual’,<br> ‘ExterCond’,’ExterQual’,’FireplaceQu’,’Functional’,’GarageCond’,<br> ‘GarageQual’,’HeatingQC’,’KitchenQual’,’LandSlope’,’PavedDrive’,’PoolQC’,<br> ‘Street’,’Utilities’]<br>quan = quan + newquan <br>for i in newquan: qual.remove(i)</pre><p>This is actually a categorical feature, MSSubClass doesn’t mean the meaning of the value of number 20, and so on with other values</p><pre>df.MSSubClass = df.MSSubClass.map({20:’class1&#39;, 30:’class2&#39;, 40:’class3&#39;, 45:’class4&#39;,<br> 50:’class5&#39;, 60:’class6&#39;, 70:’class7&#39;, 75:’class8&#39;,<br> 80:’class9&#39;, 85:’class10&#39;, 90:’class11&#39;, 120:’class12&#39;,<br> 150:’class13&#39;, 160:’class14&#39;, 180:’class15&#39;, 190:’class16&#39;})</pre><p>Keeping “YrSold” is enough, the month MoSold: Month Sold (MM) and YrSold: Year Sold (YYYY) is like a redundant feature in somehow.</p><pre>df=df.drop(‘MoSold’,axis=1)</pre><p>Update my lists of numerical and categorical features</p><pre>quan.remove(‘MoSold’)<br>quan.remove(‘MSSubClass’)<br>qual.append(‘MSSubClass’)</pre><pre>df[‘Age’] = df.YrSold — df.YearBuilt<br>df[‘AgeRemod’] = df.YrSold — df.YearRemodAdd<br>df[‘AgeGarage’] = df.YrSold — df.GarageYrBlt</pre><p>For the houses without a Garage, I filled the NANs with zeros, which makes AgeGarage ~ 2000.<br>Here I replace their AgeGarage with the maximum value among the houses with Garages</p><pre>max_AgeGarage = np.max(df.AgeGarage[df.AgeGarage &lt; 1000])<br>df[‘AgeGarage’] = df[‘AgeGarage’].map(lambda x: max_AgeGarage if x &gt; 1000 else x)</pre><p>Some of the values are negative because the work was done after the house was sold. In these cases, I change them to zero to avoid negative ages.</p><pre>df.Age = df.Age.map(lambda x: 0 if x &lt; 0 else x)<br>df.AgeRemod = df.AgeRemod.map(lambda x: 0 if x &lt; 0 else x)<br>df.AgeGarage = df.AgeGarage.map(lambda x: 0 if x &lt; 0 else x)</pre><p>drop the original time variables</p><pre>df=df.drop([‘YrSold’,’YearBuilt’,’YearRemodAdd’,’GarageYrBlt’],axis=1)</pre><p>Update the list of numerical features</p><pre>for i in [‘YrSold’,’YearBuilt’,’YearRemodAdd’,’GarageYrBlt’]: quan.remove(i)<br>quan = quan + [‘Age’,’AgeRemod’,’AgeGarage’]</pre><h3>Detect the Outliers</h3><p>These are somewhat arbitrary</p><pre># These are somewhat arbitrary <br>index_drop = df.LotFrontage[df.LotFrontage &gt; 300].index<br>index_drop = np.append(index_drop, df.LotArea[df.LotArea &gt; 100000].index)<br>index_drop = np.append(index_drop, df.BsmtFinSF1[df.BsmtFinSF1 &gt; 4000].index)<br>index_drop = np.append(index_drop, df.TotalBsmtSF[df.TotalBsmtSF &gt; 6000].index)<br>index_drop = np.append(index_drop, df[‘1stFlrSF’][df[‘1stFlrSF’] &gt; 4000].index)<br>index_drop = np.append(index_drop, df.GrLivArea[(df.GrLivArea &gt; 4000) &amp; (df.SalePrice &lt; 13)].index)<br>index_drop = np.unique(index_drop)</pre><p>Make sure we only remove data from the training set</p><pre>index_drop = index_drop[index_drop &lt; 1460]<br>df = df.drop(index_drop).reset_index(drop=True)<br>print(“{} examples in the training set are dropped.”.format(len(index_drop)))</pre><p>The output:</p><pre>7 examples in the training set are dropped.</pre><h4>Transform the numerical features that are skewed.</h4><p>It is necessary to transform the numerical features that are skewed. This is because lots of regression models building assume that the features are distributed normally and have asymmetrical shapes. For most machine learning algorithms, especially linear models, normally distributed features gives us better results.</p><pre>from scipy.stats import skew<br>for i in quan:<br> print(i+’: {}’.format(round(skew(df[i]),2)))</pre><p>The output:</p><pre>LotFrontage: 0.76<br>LotArea: 3.6<br>OverallQual: 0.19<br>OverallCond: 0.57<br>MasVnrArea: 2.63<br>BsmtFinSF1: 0.98<br>BsmtFinSF2: 4.16<br>BsmtUnfSF: 0.92<br>TotalBsmtSF: 0.67<br>1stFlrSF: 1.26<br>2ndFlrSF: 0.86<br>LowQualFinSF: 12.07<br>GrLivArea: 1.07<br>BsmtFullBath: 0.62<br>BsmtHalfBath: 3.94<br>FullBath: 0.17<br>HalfBath: 0.69<br>BedroomAbvGr: 0.33<br>KitchenAbvGr: 4.3<br>TotRmsAbvGrd: 0.75<br>Fireplaces: 0.73<br>GarageCars: -0.22<br>GarageArea: 0.22<br>WoodDeckSF: 1.84<br>OpenPorchSF: 2.53<br>EnclosedPorch: 4.0<br>3SsnPorch: 11.36<br>ScreenPorch: 3.94<br>PoolArea: 17.67<br>MiscVal: 21.94<br>Alley: 4.13<br>BsmtCond: -3.6<br>BsmtExposure: 1.12<br>BsmtFinType1: -0.15<br>BsmtFinType2: 3.16<br>BsmtQual: -1.27<br>ExterCond: 1.31<br>ExterQual: 0.78<br>FireplaceQu: 0.61<br>Functional: 3.39<br>GarageCond: -3.38<br>GarageQual: -3.26<br>HeatingQC: -0.55<br>KitchenQual: 0.39<br>LandSlope: -4.98<br>PavedDrive: -2.97<br>PoolQC: 26.93<br>Street: -16.18<br>Utilities: -33.93<br>Age: 0.6<br>AgeRemod: 0.45<br>AgeGarage: 0.97</pre><p>Transform those with skewness &gt; 0.5</p><pre>skewed_features = np.array(quan)[np.abs(skew(df[quan])) &gt; 0.5]<br>df[skewed_features] = np.log1p(df[skewed_features])</pre><h4>Dummy variables for the categorical features</h4><p>Create a list of dummy variables that I will drop, which will be the last column generated from each categorical feature</p><pre>dummy_drop = []<br>for i in qual:<br> dummy_drop += [ i+’_’+str(df[i].unique()[-1]) ]</pre><p>Create dummy variables</p><pre>df = pd.get_dummies(df,columns=qual) </pre><h4>Drop the last column generated from each categorical feature</h4><pre>df = df.drop(dummy_drop,axis=1)</pre><h4>Check nulls values</h4><pre>fig, ax = plt.subplots( figsize = (18, 6))<br>sns.heatmap(df.isnull(), yticklabels=False, cbar=False, cmap=’viridis’)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*toKlY9GiLE3mqmzFGtFzcA.png" /><figcaption>Heat map of null values</figcaption></figure><ul><li>Half of the SalePrice is null which is the test set before merging datasets.</li></ul><h4>Split the Data</h4><pre>X_train = df[:-1459].drop([‘SalePrice’,’Id’], axis=1)<br>y_train = df[:-1459][‘SalePrice’]<br>X_test = df[-1459:].drop([‘SalePrice’,’Id’], axis=1)</pre><h4>Scaling</h4><p>Fit the training set only, then transform both the training and test sets.</p><pre>scaler = RobustScaler()<br>X_train[quan]= scaler.fit_transform(X_train[quan])<br>X_test[quan]= scaler.transform(X_test[quan])<br>X_train.shape, X_test.shape</pre><h4>The output:</h4><pre>((1453, 193), (1459, 193))</pre><p>Now we have 193 features!</p><p>By Jason Brownlee on August 17, 2016, in XGBoost. Last Updated on April 22, 2020. XGBoost is an algorithm that has recently been dominating applied machine learning and Kaggle competitions for structured or tabular data. XGBoost is an implementation of gradient boosted decision trees designed for speed and performance.</p><p>XGBoost is a scalable and accurate implementation of gradient boosting machines and it has proven to push the limits of computing power for boosted trees algorithms as it was built and developed for the sole purpose of model performance and computational speed.</p><p>Feature importance is defined only for tree boosters</p><pre>!pip install xgboost<br>from xgboost import XGBRegressor<br>xgb = XGBRegressor()<br>xgb.fit(X_train, y_train)<br>imp = pd.DataFrame(xgb.feature_importances_ ,columns = [&#39;Importance&#39;],index = X_train.columns)<br>imp = imp.sort_values([&#39;Importance&#39;], ascending = False)</pre><pre>print(imp)</pre><p>The output:</p><pre>Requirement already satisfied: xgboost in c:\users\maemt\anaconda3\lib\site-packages (1.3.1)<br>Requirement already satisfied: numpy in c:\users\maemt\anaconda3\lib\site-packages (from xgboost) (1.19.2)<br>Requirement already satisfied: scipy in c:\users\maemt\anaconda3\lib\site-packages (from xgboost) (1.5.2)<br>                   Importance<br>GarageCond           0.298127<br>GarageCars           0.157924<br>OverallQual          0.079050<br>CentralAir_Y         0.052237<br>KitchenQual          0.037871<br>...                       ...<br>Fence_GdPrv          0.000000<br>Condition2_RRAn      0.000000<br>Condition2_PosN      0.000000<br>Condition2_PosA      0.000000<br>Exterior2nd_Stone    0.000000</pre><pre>[193 rows x 1 columns]</pre><p>The most 10 important features are:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/343/1*oD4hvrsRJWekz_mB_0tlWQ.png" /><figcaption>most 10 important features</figcaption></figure><p>Feature ranking with recursive feature elimination and cross-validated selection of the best number of features.</p><pre>from sklearn.metrics import make_scorer <br>from sklearn.feature_selection import RFECV</pre><pre># Define a function to calculate RMSE<br>def rmse(y_true, y_pred):<br> return np.sqrt(np.mean((y_true-y_pred)**2))</pre><pre># Define a function to calculate negative RMSE (as a score)<br>def nrmse(y_true, y_pred):<br> return -1.0*rmse(y_true, y_pred)<br>neg_rmse = make_scorer(nrmse)<br>estimator = XGBRegressor()<br>selector = RFECV(estimator, cv = 3, n_jobs = -1, scoring = neg_rmse)<br>selector = selector.fit(X_train, y_train)</pre><pre>print(“The number of selected features is: {}”.format(selector.n_features_))</pre><pre>features_kept = X_train.columns.values[selector.support_] <br>X_train = X_train[features_kept]<br>X_test = X_test[features_kept]</pre><h4>The output is:</h4><pre>The number of selected features is: 42</pre><p>So finally we can deal with cleaned 42 features rather than 81 features.</p><p>Thank you for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ec45bb960a1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Web Scraping and Regular Expressions: Doing it by Python.]]></title>
            <link>https://monirah-abdulaziz.medium.com/web-scraping-and-regular-expressions-doing-it-by-python-f770394f0a89?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/f770394f0a89</guid>
            <category><![CDATA[beautifulsoup]]></category>
            <category><![CDATA[regex]]></category>
            <category><![CDATA[noon]]></category>
            <category><![CDATA[selenium]]></category>
            <category><![CDATA[web-scraping]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Mon, 01 Mar 2021 18:21:24 GMT</pubDate>
            <atom:updated>2021-03-01T18:21:24.591Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Qh3GaeBA59gx9ZMB.jpg" /><figcaption>source: shorturl.at/ahjAX</figcaption></figure><p>With the largest online selection of leading brands in categories such as electronics, fashion, health &amp; beauty, fragrances, grocery, baby products, and homeware, noon is the one-stop-shopping destination for everyone. In this article, I choose the noon website, data was collected from the perfume section for female, male, and kids departments.</p><p>This article talks about web scraping and regex to extract required data from this website.</p><h3>What is Web Scraping?</h3><p>If you wonder what web scraping is, “Web scraping is a technique of extracting information from websites. It focuses on the transformation of unstructured data on the web, into structured data that can be stored and analyzed”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/0*omK69NeOyLMDpHbd" /><figcaption>web scraping</figcaption></figure><h3>What are Regular Expressions?</h3><blockquote>A regular expression is a <strong>sequence of characters that define a search pattern</strong>.</blockquote><blockquote>Usually this pattern is then used by <strong>string searching algorithms</strong> for “find” or “find and replace” operations on strings</blockquote><h4>The Most Famous Quote in regex-dom</h4><blockquote><em>“Some people, when confronted with a problem, think ‘I know, I’ll use regular expressions.’ Now they have two problems.” — Jamie Zawinski (Netscape engineer)</em></blockquote><p>There are many places where regex can be run — from your text editor to the bash shell to Python, and even SQL. It is typically baked into the standard library of programming languages.</p><p>In Python, it can be imported like so:</p><pre><strong>import</strong> <strong>re</strong></pre><h4>As a Data scientist, when to use Regular Expressions?</h4><p>Regular Expressions help in manipulating textual <strong>data</strong>, which is often a pre-requisite for <strong>data science</strong> projects that involve text analytics.</p><h3>The dataset</h3><p>After using selenium and beautiful soup to create our dataset, it looks like that:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TMX91rBHhys1x_e2by9VDg.png" /><figcaption>dataset before cleaning</figcaption></figure><p>there are many data that could be extracted from the above features, lets see:</p><h4>To extract ml from perfume name:</h4><pre>df[&#39;ml&#39;] = df[&#39;name&#39;].str.extract(&#39;(\d+ml)&#39;, expand=<strong>False</strong>)<br>df[&#39;name&#39;] = df.apply(<strong>lambda</strong> row : row[&#39;name&#39;].replace(str(row[&#39;ml&#39;]), &#39;&#39;), axis=1)</pre><h4>To extract brand from perfume name:</h4><pre>df[&#39;name&#39;] = df.apply(<strong>lambda</strong> row : row[&#39;name&#39;].replace(str(row[&#39;brand&#39;]), &#39;&#39;), axis=1)</pre><h4>To extract concentration from perfume name:</h4><pre><br>df[&#39;concentration&#39;] = df[&#39;name&#39;].str.extract(&#39;(.{3,5})$&#39;, expand=<strong>False</strong>)<br>df[&#39;name&#39;] = df.name.str.replace(r&#39;(.{3,5})$&#39;, &#39;&#39;, regex=<strong>True</strong>)</pre><h4>To extract notes, scents, dispenser_type, andaromatherapy_type from the details feature:</h4><pre><br>df[&#39;Base Note&#39;]=df[&#39;details&#39;].str.extract(&#39;((?&lt;=Base Note).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;fragrance_notes&#39;]=df[&#39;details&#39;].str.extract(&#39;((?&lt;=Fragrance Notes).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;middle_note&#39;] = df[&#39;details&#39;].str.extract(&#39;((?&lt;=Heart/Middle Note).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;department&#39;] = df[&#39;details&#39;].str.extract(&#39;((?&lt;=Department).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;scents&#39;] = df[&#39;details&#39;].str.extract(&#39;((?&lt;=Scents/Notes).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;dispenser_type&#39;] = df[&#39;details&#39;].str.extract(&#39;((?&lt;=Dispenser Type).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;top_note&#39;] = df[&#39;details&#39;].str.extract(&#39;((?&lt;=Top Note).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)<br>df[&#39;aromatherapy_type&#39;] = df[&#39;details&#39;].str.extract(&#39;((?&lt;=Aromatherapy Type).+?(?= &amp;))&#39; ,expand=<strong>False</strong>)</pre><h4>To extract the number of seller ratings, scents, dispenser_type, andaromatherapy_type from the details feature:</h4><pre>df[&#39;num_seller_ratings&#39;]= df.num_seller_ratings.str.replace(r&#39;[()]&#39;, &#39;&#39;, regex=<strong>True</strong>)<em>#.str.strip()</em><br>df[&#39;seller_rating&#39;] = df[&#39;num_seller_ratings&#39;].str.extract(&#39;^(.{0,3})&#39; ,expand=<strong>False</strong>)<em>#  .str.replace</em><br>df[&#39;num_seller_ratings&#39;]= df.num_seller_ratings.str.replace(&#39;^(.{0,3})&#39; ,&#39;&#39;)<br></pre><p>After using regex techniques:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OvVE4YUfX6mLHZ2nv3LZTw.png" /><figcaption>After using regex techniques:</figcaption></figure><h4>noon_perfume Data Dictionary:</h4><p>Here Data Dictionary after cleaning and feature engineering.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rYCJXYu7-e-RWIVXOPzIxg.png" /><figcaption>data dictionary</figcaption></figure><p>So from8 features we extracted 18 features, GREAT:)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f770394f0a89" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Goodreads Books Recommendation System]]></title>
            <link>https://monirah-abdulaziz.medium.com/goodreads-books-recommendation-system-619dc190c81?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/619dc190c81</guid>
            <category><![CDATA[recommendation-system]]></category>
            <category><![CDATA[goodreads]]></category>
            <category><![CDATA[books]]></category>
            <category><![CDATA[mls]]></category>
            <category><![CDATA[content-based-filtering]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Sun, 28 Feb 2021 16:19:47 GMT</pubDate>
            <atom:updated>2021-02-28T16:19:47.068Z</atom:updated>
            <content:encoded><![CDATA[<p>Done by: <a href="https://medium.com/u/87f03ec137ee">Lamalharbi</a>, <a href="https://medium.com/u/20e1553c7e2c">Aisha Y Hakami</a> and <a href="https://medium.com/u/cac8f1becf29">Monirah abdulaziz</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*QuPoUxix3VvqoqxHr5_-Xg.png" /><figcaption>source: <a href="https://www.goodreads.com/">https://www.goodreads.com/</a></figcaption></figure><p>In this blog, we will see how we can build a simple content-based recommender system using <a href="http://goodreads.com/">Goodreads.com</a> data, computer books, particularly, this data obtained from <a href="https://www.kaggle.com/muneeralhajri/goodreadscomputerbooks">Kaggle</a>.</p><p>Usually, we plan to buy a book specially the scientific books, we normally ask about the goods ones, research the book domains, compare the books with similar or read the reviews so here the recommender system is the master of this problem.</p><h3>Recommendation system algorithms:</h3><h3>Content-based recommendation system (CB)</h3><p>Content-based recommendation systems recommend items to a user by using the similarity of items. This recommender system recommends products or items based on their description or features. It identifies the similarity between the products based on their descriptions. It also considers the user’s previous history in order to recommend a similar product.</p><p><em>Pros and Cons of content-based recommendation</em> <em>techniques</em></p><h3>Pros :</h3><ol><li>No cold-start problem, unlike Collaborative Filtering, if the programs have sufficient descriptions, we avoid the “new item problem”.</li><li>Able to recommend to users with unique tastes</li><li>Able to recommend new &amp; unpopular items — No first-rater problem.</li></ol><h3>Cons :</h3><ol><li>Content-Based tend to over-specialization: they will recommend items similar to those already consumed, with a tendency of creating a “filter bubble”.</li><li>Never recommends items outside the user’s content profile, people might have multiple interests.</li></ol><h3>Collaborative Filtering (CL)</h3><p>This filtration strategy is based on the combination of the user’s behavior and comparing and contrasting that with other users’ behavior in the database. The history of all users plays an important role in this algorithm. The main difference between content-based filtering and collaborative filtering that in the latter, the interaction of all users with the items influences the recommendation algorithm while for content-based filtering only the concerned user’s data is taken into account.</p><p><em>Pros and Cons of collaborative filtering techniques</em></p><p>Pros:</p><ol><li>Collaborative filtering systems work by people in the system, and it is expected that people to be better at evaluating information than a computed function.</li></ol><p>Cons:</p><ol><li>Cold Start: a major challenge of the Collaborative Filtering technique can be how to make recommendations for a new user who has recently entered the system; that is called the cold-start user problem.</li><li>Sparsity:</li></ol><ul><li>The user/rating matrix is sparse.</li><li>Hard to find users that have rated the same items.</li></ul><p>3. First rater:</p><ul><li>Cannot recommend an item that has not been previously rated.</li><li>New items, Esoteric items.</li></ul><p>4. Popularity bias:</p><ul><li>Cannot recommend items to someone with a unique taste.</li><li>Tends to recommend popular items.</li></ul><p>As I mentioned above, we are using <a href="http://goodreads.com/">Amazon.com</a> data and don’t have a user reading history. Hence, we have used a simple content-based recommendation system. We are going to build two recommendation systems by using a book title and book description.</p><p>We need to find similar books to a given book and then recommend those similar books to the user. How do we find whether the given book is similar or dissimilar? A similarity measure was used to find this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gOhuf46zyWQKInVx.png" /><figcaption>source: shorturl.at/ivGRY</figcaption></figure><h4>The Data:</h4><p>This data contains information about different Computer books:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/592/1*RJowNIFhpPVlRqQRTknCfA.png" /><figcaption>Data dictionary</figcaption></figure><h4>The head of the table:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7EPfBPWZFbPP4M4SqBFC5w.png" /><figcaption>The head of the table.</figcaption></figure><h4>Check Nulls</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/258/1*AUMtJol3_1QuuUKSFvbr-g.png" /><figcaption>Null values</figcaption></figure><h3>EDA</h3><p>Since the columnBook_Id is as an index, we will drop it and generate a new ID.</p><pre>df.drop([&#39;Book_Id&#39;],axis<strong>=</strong>1,inplace<strong>=True</strong>)</pre><ul><li>Check duplicates and drop if exists.</li></ul><pre>df.shape</pre><p>(1234, 9)</p><pre>df[df[&#39;book_Title&#39;]<strong>==</strong>&#39;Anime and the Visual Novel: Narrative Structure Design and Play at the Crossroads of Animation and Computer Games&#39;]</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oEonXi2E7QMZ59bF.png" /><figcaption>Sample of duplicated rows</figcaption></figure><h4>drop_duplicates and check the shape</h4><pre>df.drop_duplicates(inplace<strong>=True</strong>)<br>df.shape</pre><p>(1142, 9)</p><pre>df[df[&#39;book_Title&#39;]<strong>==</strong>&#39;Anime and the Visual Novel: Narrative Structure Design and Play at the Crossroads of Animation and Computer Games&#39;]</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YLPVX2ABaShjmvRF.png" /><figcaption>Confirm that the duplicated rows are removed</figcaption></figure><pre># Generate a new id <br>df=df.assign(id=(df[&#39;book_Title&#39;]).astype(&#39;category&#39;).cat.codes)<br>df.head()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/45/0*vXFAPN9tOFgb94wW" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*n_W3nyHuRH49esbN.png" /><figcaption>after assigning new ID</figcaption></figure><h3>Visualization</h3><h4>Most frequent authors</h4><pre>plt.subplots(figsize<strong>=</strong>(10,7))<br>df.Author_Name.value_counts()[:10].plot(kind<strong>=</strong>&quot;bar&quot;)<br>plt.show()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4AvZrtFPhj-2layb.png" /><figcaption>Most frequent authors</figcaption></figure><p>Donald Ervin Knuth, Gray B.Shelly, and Sumita Arora are the most 3 frequent authors.</p><h4>Calculating and plotting the word count for book_Title</h4><pre># Calculating the word count for book description<br>df[‘book_Title’] = df[‘book_Title’].apply(lambda x: len(str(x).split()))# Plotting the word count<br>df[‘book_Title’].plot(<br> kind=’hist’,<br> bins = 50,<br> figsize = (12,8),title=’Word Count Distribution for book_Title’)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g8KrhDiW4jFMRvBkQ0G57Q.png" /><figcaption>Word Count Distribution for book_Title</figcaption></figure><ul><li>The majority of the book&#39;s title is between 5~10 words.</li><li>The distribution of the book’s title is right-skewed.</li></ul><h3>Content-Based Recommender Systems</h3><pre># test poinst for ratings_count=40, Avg_Rating= 4.5, Publish_year= 2002, Pages_no= 523<br>test_point = [40, 4.5, 2002, 523]<br>X = df.iloc[:, [2, 3, 4, 6]].values# build a nearest neighbor object, we are searching for just 3 neighbors so n_neighbors=3<br>nn = NearestNeighbors(n_neighbors=3).fit(X)<br># kneighbors returns the neighbor for the test_point<br>print(nn.kneighbors([test_point]))</pre><p>(array([[ 3.9028323 , 7.91060048, 12.2137791 ]]), array([[626, 445, 486]]))</p><pre># This is the most similar book from all the available books<br>df.iloc[626].to_frame()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/684/0*yA96Oys0g1Z-ORFY.png" /></figure><pre>df.iloc[445].to_frame()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/646/0*EGPW4VotiU-6L9ZG.png" /></figure><p>From the above results, we can observe that the recommender books are similar to the test points that we fed manually to the model.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=619dc190c81" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Titanic — Machine Learning from Disaster — Data Cleaning]]></title>
            <link>https://monirah-abdulaziz.medium.com/titanic-machine-learning-from-disaster-data-cleaning-a61be731c0cc?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/a61be731c0cc</guid>
            <category><![CDATA[mls]]></category>
            <category><![CDATA[kaggle]]></category>
            <category><![CDATA[data-analytics]]></category>
            <category><![CDATA[titanic]]></category>
            <category><![CDATA[cleaning]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Sun, 28 Feb 2021 14:47:34 GMT</pubDate>
            <atom:updated>2021-02-28T14:47:34.183Z</atom:updated>
            <content:encoded><![CDATA[<h3>Titanic — Machine Learning from Disaster — Data Cleaning</h3><p>Done by: <a href="https://medium.com/u/87f03ec137ee">Lamalharbi</a>, <a href="https://medium.com/u/20e1553c7e2c">Aisha Y Hakami</a>, and <a href="https://medium.com/u/cac8f1becf29">Monirah abdulaziz</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1020/1*qmUFUhQ0nsiKbXxcBYSrDg.png" /><figcaption>src: <a href="https://www.forbes.com/sites/davidbressan/2019/04/14/a-geological-study-of-the-titanic-shipwreck-site/?sh=60fd0046431a">TitanicShip</a></figcaption></figure><h3>Introduction</h3><p>This article goes through the whole process of cleaning the data and developing a machine learning model on the Titanic dataset which is one of the famous data sets which every Data Scientist explores at the start of their career and here we are. The dataset provides all the information on the fate of passengers on the Titanic, summarized according to sex, age, economic status (class), and survival.</p><p>In addition, you can join the <a href="https://www.kaggle.com/c/titanic/overview">Titanic: Machine Learning from Disaster</a> challenge on Kaggle.</p><h3>Data Cleaning</h3><pre># upload the data<br>train = pd.read_csv(&#39;../datasets/train.csv&#39;)<br>test = pd.read_csv(&#39;../datasets/test.csv&#39;)</pre><h4>Check the null values:</h4><pre>fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (18, 6))# train data <br>sns.heatmap(train.isnull(), yticklabels=False, ax = ax[0], cbar=False, cmap=&#39;viridis&#39;)<br>ax[0].set_title(&#39;Train data&#39;)# test data<br>sns.heatmap(test.isnull(), yticklabels=False, ax = ax[1], cbar=False, cmap=&#39;viridis&#39;)<br>ax[1].set_title(&#39;Test data&#39;);</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ib0vFoj0xP1o8CdN.png" /><figcaption>Heatmap to visualize the null values before cleaning</figcaption></figure><p><strong>Observation</strong>:</p><ul><li>There are missing values in the train set: Age, Cabin and Embarked.</li><li>There are missing values in the test set: Age, Fare and Cabin.</li></ul><h4>1. Embarked feature in Train</h4><p>First, we need to check How many ports are in Embarked column:</p><pre>train.Embarked.value_counts()</pre><p>The result was:</p><p>S 644<br>C 168<br>Q 77</p><p>Well, now we can drop the two rows with missing Embarked values in the train set, however, let&#39;s fill the nulls with the port of highest embarkation.</p><pre>from collections import Countertrain.Embarked= train.Embarked.replace(np.nan,Counter(train.Embarked).most_common(1)[0][0])</pre><h4>2. Fare feature in Test</h4><p>To fill the missing values in Fare we can use the Pclass column, by computing the average of Fare of the missing Class.</p><pre>class3_mean = train[train[&#39;Pclass&#39;]==3][&#39;Fare&#39;].mean()<br>test[&#39;Fare&#39;] = test[&#39;Fare&#39;].replace({np.nan:class3_mean})</pre><h4>3. Age feature in Train and Test</h4><pre>#defining a function &#39;impute_age&#39;<br>def impute_age(age_pclass): # passing age_pclass as [&#39;Age&#39;, &#39;Pclass&#39;]<br>    <br>    # Passing age_pclass[0] which is &#39;Age&#39; to variable &#39;Age&#39;<br>    Age = age_pclass[0]<br>    <br>    # Passing age_pclass[2] which is &#39;Pclass&#39; to variable &#39;Pclass&#39;<br>    Pclass = age_pclass[1]<br>    <br>    #applying condition based on the Age and filling the missing data respectively <br>    if pd.isnull(Age):if Pclass == 1:<br>            return 38elif Pclass == 2:<br>            return 30else:<br>            return 25else:<br>        return Age</pre><p>By using the above function we can<strong> </strong>fill the missing data in Age the feature according to the mean age with respect to each Pclass.</p><pre># (for train) grab age and apply the impute_age, our custom function<br>train[&#39;Age&#39;] = train[[&#39;Age&#39;,&#39;Pclass&#39;]].apply(impute_age,axis=1)</pre><pre># (for test) grab age and apply the impute_age, our custom function <br>test[&#39;Age&#39;] = test[[&#39;Age&#39;,&#39;Pclass&#39;]].apply(impute_age,axis=1)</pre><p>4. Cabin feature in Train and Test</p><p>Now we reach half of the way, the last step is the Cabin , the column we need to apply some feature engineering.</p><ul><li>If there was a value for Cabin — replace it with <strong>1</strong></li><li>If the value is missing/null — replace it with <strong>0</strong></li></ul><pre>#Train:<br>train.loc[train[&#39;Cabin&#39;].notnull(), &#39;Cabin&#39;] =1<br>train[&#39;Cabin&#39;] = train[&#39;Cabin&#39;].replace({np.nan:0})<br>train[&#39;Cabin&#39;] = train[&#39;Cabin&#39;].astype(int)</pre><pre>#Test:<br>test.loc[test[&#39;Cabin&#39;].notnull(), &#39;Cabin&#39;] =1<br>test[&#39;Cabin&#39;] = test[&#39;Cabin&#39;].replace({np.nan:0})<br>test[&#39;Cabin&#39;] = test[&#39;Cabin&#39;].astype(int)</pre><p>Now let’s take a look at the heatmap again:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TEeNOXXRCeiX0FE7.png" /><figcaption>Heatmap to visualize the null values after cleaning</figcaption></figure><h4>Look’s Great!! No more missing values :)</h4><h3>Feature Engineering</h3><p>To include the categorical variables as predictors in statistical and machine learning models we need to Dummy the variables.</p><p>Dummy the Sex and Embarked columns</p><pre># Train<br>sex = pd.get_dummies(train[&#39;Sex&#39;],drop_first=True)<br>embark = pd.get_dummies(train[&#39;Embarked&#39;],drop_first=True)<br>train = pd.concat([train, sex,embark],axis=1)<br>train=train.drop([&#39;Sex&#39;,&#39;Embarked&#39;], axis=1)<br>train.rename(columns={&quot;male&quot;: &quot;sex_male&quot;, &quot;Q&quot;: &quot;Embarked_Q&quot;,&quot;S&quot;: &quot;Embarked_S&quot;}, inplace=True)<br># Same for the Test</pre><h3>Model Preparation</h3><ol><li>First, we need to select our features and it will be the following:</li></ol><p>[Pclass, Age, SibSp, Parch, Fare, Cabin, Sex_male, Embarked_Q, Embarked_S]</p><p>And our target will be the feature: Survived</p><p>2. Then we need to write a list comprehension to grab the selected features.</p><p>3. Separate the selected_column in X_train and the Survived in y_train.</p><pre>features_drop = [&#39;PassengerId&#39;,&#39;Name&#39;, &#39;Ticket&#39;, &#39;Survived&#39;]<br>selected_features = [x for x in train.columns  if x not in features_drop ]<br>X_train = train[selected_features]<br>y_train = train[&#39;Survived&#39;]</pre><p><strong>Now the data is ready to train on the models.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a61be731c0cc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Children Books Recommendation System]]></title>
            <link>https://monirah-abdulaziz.medium.com/children-books-recommendation-system-d628425d70cc?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/d628425d70cc</guid>
            <category><![CDATA[amazon]]></category>
            <category><![CDATA[children-books]]></category>
            <category><![CDATA[recommendation-system]]></category>
            <category><![CDATA[books]]></category>
            <category><![CDATA[content-based-filtering]]></category>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Sun, 28 Feb 2021 14:17:19 GMT</pubDate>
            <atom:updated>2021-02-28T14:17:19.966Z</atom:updated>
            <content:encoded><![CDATA[<h4>Done by: <a href="https://medium.com/u/cac8f1becf29">Monirah abdulaziz</a>, <a href="https://medium.com/u/87f03ec137ee">Lamalharbi</a>, and <a href="https://medium.com/u/20e1553c7e2c">Aisha Y Hakami</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/751/1*vIeg4LActLIQ9R1GPa29eQ.png" /><figcaption><a href="https://wfpl.net/book-recommendations">s</a>ource: shorturl.at/xyW02</figcaption></figure><h3>Problem Statement:</h3><p>Build a Recommendation System for children&#39;s books from amazon, a dataset that scrapped by Modhi almannaa,<a href="https://www.kaggle.com/modhiibrahimalmannaa/1000-children-books-on-amazom"> <em>see the link</em></a><em>.</em></p><p>This dataset was scraped from Amazon, the largest selling platform, it provides all the information that helps the customers to find the best products, by reviewing all the information the customer needs to know before buying the product. This dataset focused only on children&#39;s books.</p><h3>Recommendation system algorithms:</h3><h4>Content-based recommendation system (CB)</h4><p>Content-based recommendation systems recommend items to a user by using the similarity of items. This recommender system recommends products or items based on their description or features. It identifies the similarity between the products based on their descriptions. It also considers the user’s previous history in order to recommend a similar product.</p><p><em>Pros and Cons of content-based recommendation</em> <em>techniques</em></p><h4>Pros :</h4><ol><li>No cold-start problem, unlike Collaborative Filtering, if the programs have sufficient descriptions, we avoid the “new item problem”.</li><li>Able to recommend to users with unique tastes</li><li>Able to recommend new &amp; unpopular items — No first-rater problem.</li></ol><h4>Cons :</h4><ol><li>Content-Based tend to over-specialization: they will recommend items similar to those already consumed, with a tendency of creating a “filter bubble”.</li><li>Never recommends items outside the user’s content profile, people might have multiple interests.</li></ol><h4>Collaborative Filtering (CL)</h4><p>This filtration strategy is based on the combination of the user’s behavior and comparing and contrasting that with other users’ behavior in the database. The history of all users plays an important role in this algorithm. The main difference between content-based filtering and collaborative filtering that in the latter, the interaction of all users with the items influences the recommendation algorithm while for content-based filtering only the concerned user’s data is taken into account.</p><p><em>Pros and Cons of collaborative filtering techniques</em></p><p>Pros:</p><ol><li>Collaborative filtering systems work by people in the system, and it is expected that people to be better at evaluating information than a computed function.</li></ol><p>Cons:</p><ol><li>Cold Start: a major challenge of the Collaborative Filtering technique can be how to make recommendations for a new user who has recently entered the system; that is called the cold-start user problem.</li><li>Sparsity:</li></ol><ul><li>The user/rating matrix is sparse.</li><li>Hard to find users that have rated the same items.</li></ul><p>3. First rater:</p><ul><li>Cannot recommend an item that has not been previously rated.</li><li>New items, Esoteric items.</li></ul><p>4. Popularity bias:</p><ul><li>Cannot recommend items to someone with a unique taste.</li><li>Tends to recommend popular items.</li></ul><p>As I mentioned above, we are using <a href="http://goodreads.com/">Amazon.com</a> data and don’t have a user reading history. Hence, we have used a simple content-based recommendation system. We are going to build two recommendation systems by using a book title and book description.</p><p>We need to find similar books to a given book and then recommend those similar books to the user. How do we find whether the given book is similar or dissimilar? A similarity measure was used to find this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pp1SjHBMP2rM1Vgxw1m6gw.png" /><figcaption>source: shorturl.at/ivGRY</figcaption></figure><h3>The Data</h3><p>This data contains information about different children books:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/615/1*73iKhdKTCBmfy4i5y4XdFA.png" /></figure><h4>The head of the table:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Xs06ccShdh80eFxejNMOrA.png" /></figure><h4>EDA and regex</h4><p>The Description feature for the first book looks like this:</p><pre>&#39;\n#1\xa0NEW YORK TIMES\xa0BESTSELLER • A modern, sophisticated suspense novel from National Book Award finalist, and Printz Award honoree E. Lockhart.A beautiful and distinguished family.A private island.A brilliant, damaged girl; a passionate, political boy.A group of four friends—the Liars—whose friendship turns destructive.A revolution. An accident. A secret.Lies upon lies.True love.The truth.Read it.And if anyone asks you how it ends, just LIE.&quot;Thrilling, beautiful, and blisteringly smart, We Were Liars is utterly unforgettable.&quot; —John Green, #1 New York Times bestselling author of The Fault in Our Stars\n\n&#39;</pre><p>The Product_Details feature for the first book looks like this:</p><pre>&#39;\n\n\n\nProduct details\n\n\n\n\n\nPublisher\n:\n\nEmber; Illustrated edition (May 29, 2018)\n\n\nLanguage\n:\n\nEnglish\n\n\nPaperback\n:\n\n320 pages\n\n\nISBN-10\n:\n\n0385741278\n\n\nISBN-13\n:\n\n978-0385741279\n\n\nReading age\n:\n\n12 - 17 years\n\n\nLexile measure\n:\n\n600L\n\n\nGrade level\n:\n\n7 - 9\n\n\nItem Weight\n:\n\n12 ounces\n\n\nDimensions\n:\n\n5.49 x 0.84 x 8.24 inches\n\n\n\n\n\n\nBest Sellers Rank:\n\n#13 in Books (See Top 100 in Books)\n\n #1 in Teen &amp; Young Adult Family Fiction\n #1 in Teen &amp; Young Adult Fiction about Emotions &amp; Feelings\n #1 in Teen &amp; Young Adult Fiction about Death &amp; Dying\n\n\n\n\n\n\nCustomer Reviews:\n\n\n\n\n\n\n\n4.5 out of 5 stars\n\n\n\n\n\n\n\n\n12,959 ratings\n\n\n\n\n\n\n\n\n\n\n\n\n&#39;</pre><p>And after some regex:</p><pre>&#39;Product detailsPublisher:Ember; Illustrated edition (May 29, 2018)Language:EnglishPaperback:320 pagesISBN-10:0385741278ISBN-13:978-0385741279Reading age:12 - 17 yearsLexile measure:600LGrade level:7 - 9Item Weight:12 ouncesDimensions:5.49 x 0.84 x 8.24 inchesBest Sellers Rank:#13 in Books (See Top 100 in Books) #1 in Teen &amp; Young Adult Family Fiction #1 in Teen &amp; Young Adult Fiction about Emotions &amp; Feelings #1 in Teen &amp; Young Adult Fiction about Death &amp; DyingCustomer Reviews:4.5 out of 5 stars12,959 ratings&#39;</pre><p>So we can extract a lot of information from this column like Publisher, Illustrated edition, Language, ISBN, and so on.</p><pre>df[&#39;Publisher&#39;] = df[&#39;Product_Details&#39;].str.extract(&#39;((?&lt;=Publisher:).+?(?=;))&#39; ,expand=False)#&#39;ISBN-13:.+?(?= ;)</pre><pre>df[&#39;Publisher&#39;] = df.Publisher.str.replace(r&#39;-&#39;, &#39;&#39;, regex=True).str.strip()#Program</pre><p>The new feature <em>Publisher</em> :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/141/1*cxlQHaCY49H34I4pzEZRaQ.png" /><figcaption>Publisher feature</figcaption></figure><p>The new feature <em>ISBN</em> :</p><pre>df[‘ISBN’] = df[‘Product_Details’].str.extract(‘ISBN-13:(\d+-?\d*)’, expand=False)##ISBN consists of 13 digits<br>df[‘ISBN’] = df.ISBN.str.replace(r’-’, ‘’, regex=True).str.strip()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/154/1*8qjvg-Do3J9v_vFO81ksYA.png" /><figcaption>ISBN Feature</figcaption></figure><p>So, the above two examples of how easy that extract any data by using the regex technique.</p><h4>Create a new dataframe that consists of desired features.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A6J8XVFkSQcJSHig_Vr5oQ.png" /><figcaption>new dataframe</figcaption></figure><h4>Check Nulls</h4><pre>hasNAN = df.isnull().sum()<br>hasNAN = hasNAN[hasNAN &gt; 0]<br>hasNAN = hasNAN.sort_values(ascending=False)<br>print(hasNAN,df.shape)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/347/1*Y4HdwP7pTSecmUiOa6q2SQ.png" /><figcaption>Null values of the new dataframe</figcaption></figure><p>The new dataframe shape is (1200, 6), so since we have many books and the null values less than 70%, so we will delete the null values.</p><h4>Calculating and plotting the word count for book description</h4><pre># Calculating the word count for book description<br>df[‘word_count’] = df1[‘Description’].apply(lambda x: len(str(x).split()))# Plotting the word count<br>df[‘word_count’].plot(<br> kind=’hist’,<br> bins = 50,<br> figsize = (12,8),title=’Word Count Distribution for book descriptions’)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VyUJe5K0GXDQnuePzjb2dA.png" /><figcaption>Distribution of word count for book description.</figcaption></figure><ul><li>The majority of books description are between 30~200 words.</li><li>We don’t have many lengthy book descriptions. It is clear that <a href="http://goodreads.com/">Amazon.com</a> provides short descriptions.</li><li>The distribution of books description is right-skewed.</li></ul><h4>Converting book titles into vectors using TF-IDF using Bigram</h4><pre>#Converting text descriptions into vectors using TF-IDF using Bigram<br>tf = TfidfVectorizer(ngram_range=(2, 2), stop_words=’english’, lowercase = False)<br>tfidf_matrix = tf.fit_transform(df[‘Name’])<br>total_words = tfidf_matrix.sum(axis=0) <br>#Finding the word frequency<br>freq = [(word, total_words[0, idx]) for word, idx in tf.vocabulary_.items()]<br>freq =sorted(freq, key = lambda x: x[1], reverse=True)<br>#converting into dataframe <br>bigram = pd.DataFrame(freq)<br>bigram.rename(columns = {0:’bigram’, 1: ‘count’}, inplace = True) <br>#Taking first 20 records<br>bigram = bigram.head(20)</pre><pre>##Plotting the bigram distribution<br>bigram.plot(x =’bigram’, y=’count’, kind = ‘bar’, title = “Bigram disribution for the top 20 words in the book titles”, figsize = (15,7), )</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*orZL0FvswydmqRvwNhnd9A.png" /><figcaption>Plotting the bigram distribution</figcaption></figure><ul><li>The Boxed Set, Box Set, and Harry Potter are the top 3 words in the book titles.</li></ul><h4>Converting book descriptions into vectors using TF-IDF using Bigram</h4><pre>#Converting text descriptions into vectors using TF-IDF using Bigram<br>tf = TfidfVectorizer(ngram_range=(2, 2), stop_words=’english’, lowercase = False)<br>tfidf_matrix = tf.fit_transform(df1[‘Description’])<br>total_words = tfidf_matrix.sum(axis=0) <br>#Finding the word frequency<br>freq = [(word, total_words[0, idx]) for word, idx in tf.vocabulary_.items()]<br>freq =sorted(freq, key = lambda x: x[1], reverse=True)<br>#converting into dataframe <br>bigram = pd.DataFrame(freq)<br>bigram.rename(columns = {0:’bigram’, 1: ‘count’}, inplace = True) <br>#Taking first 20 records<br>bigram = bigram.head(20)</pre><pre>##Plotting the bigram distribution<br>bigram.plot(x =’bigram’, y=’count’, kind = ‘bar’, title = “Bigram disribution for the top 20 words in the book description”, figsize = (15,7), )</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BW6lcorMoWizhFl_WO8lBw.png" /></figure><ul><li>New York, York Times, board book are the top 3 words in the book description.</li></ul><h3>Text Preprocessing</h3><h4>Cleaning the book descriptions.</h4><pre>## Function for removing NonAscii characters<br>def _removeNonAscii(s):<br> return “”.join(i for i in s if ord(i)&lt;128)</pre><pre>## Function for converting into lower case<br>def make_lower_case(text):<br> return text.lower()</pre><pre># Function for removing stop words<br>def remove_stop_words(text):<br> text = text.split()<br> stops = set(stopwords.words(“english”))<br> text = [w for w in text if not w in stops]<br> text = “ “.join(text)<br> return text</pre><pre># Function for removing punctuation<br>def remove_punctuation(text):<br> tokenizer = RegexpTokenizer(r’\w+’)<br> text = tokenizer.tokenize(text)<br> text = “ “.join(text)<br> return text</pre><pre># Function for removing the html tags<br>def remove_html(text):<br> html_pattern = re.compile(‘&lt;.*?&gt;’)<br> return html_pattern.sub(r’’, text)<br></pre><p>The above functions converting into lower case and removing HTML tags, punctuation, stop words, and NonAscii characters for the description feature.</p><pre># Applying all the functions in description and storing as a cleaned_desc<br>df1[‘cleaned_desc’] = df1[‘Description’].apply(_removeNonAscii)<br>df1[‘cleaned_desc’] = df1.cleaned_desc.apply(func = make_lower_case)<br>df1[‘cleaned_desc’] = df1.cleaned_desc.apply(func = remove_stop_words)<br>df1[‘cleaned_desc’] = df1.cleaned_desc.apply(func=remove_punctuation)<br>df1[‘cleaned_desc’] = df1.cleaned_desc.apply(func=remove_html)</pre><p>The above function store the modification into another feature that called cleaned_desc.</p><p>Comparison between description before and after cleaning:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LoPG68LUxH5Sis5mPqSPHw.png" /></figure><h4>Recommendation engine</h4><ul><li>We build a recommendation engine using book titles and descriptions.</li><li>Convert each book title and description into vectors using TF-IDF and bigram.</li><li>The model recommends a similar book based on title and description.</li><li>The model recommends a similar book based on title and description.</li><li>Define a function that takes the book title as input and returns the top five similar recommended books based on the title and description.</li></ul><pre>tfidf = TfidfVectorizer(stop_words=’english’)<br>df1[‘cleaned_desc’] = df1[‘cleaned_desc’].fillna(‘’)<br>#Construct the required TF-IDF matrix by applying the fit_transform method on the overview feature<br>overview_matrix = tfidf.fit_transform(df1[‘cleaned_desc’])<br>#Output the shape of tfidf_matrix<br>overview_matrix.shape<br></pre><pre>#similarity_matrix<br>similarity_matrix = linear_kernel(overview_matrix,overview_matrix)<br>similarity_matrix</pre><pre>#book index mapping<br>mapping = pd.Series(df1.index,index =df1[&#39;Name&#39;])<br>mapping[:3]</pre><pre>def recommend_books_based_on_plot(book_input):<br>    book_index = mapping[book_input]<br>    #get similarity values with other books<br>    #similarity_score is the list of index and similarity matrix<br>    similarity_score = list(enumerate(similarity_matrix[book_index]))<br>    #sort in descending order the similarity score of book inputted with all the other books<br>    similarity_score = sorted(similarity_score, key=lambda x: x[1], reverse=True)<br>    # Get the scores of the 5 most similar books. Ignore the first book.<br>    similarity_score = similarity_score[1:6]<br>    #return book names using the mapping series<br>    book_indices = [i[0] for i in similarity_score]<br>    return (df1[&#39;Name&#39;].iloc[book_indices])</pre><h4>Test the model</h4><p>Let&#39;s now try to get a recommendation for the book <em>‘If Animals Kissed Good Night’</em> from the above recommendation function and see what it outputs.</p><pre>recommend_books_based_on_plot(‘If Animals Kissed Good Night’).to_frame()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/439/1*rkV8rTR16tbgAo-INhLsFw.png" /><figcaption>Top 5 books recommended.</figcaption></figure><p>Top 5 books recommended that are similar to “<em>If Animals Kissed Good Night</em>”.</p><h4>Comparison between the first two books.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gPR3sNBgQN4ozLdIcyBr1g.png" /></figure><h4>Observation</h4><ul><li>From the description, we can see that the recommender books have similar points in the stories from the &#39;If Animals Kissed Good Night&#39; book.</li></ul><h4>References:</h4><ul><li><a href="https://www.kdnuggets.com/2020/07/building-content-based-book-recommendation-engine.html">https://www.kdnuggets.com/2020/07/building-content-based-book-recommendation-engine.html</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d628425d70cc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Project 1: Local Traffic, Statistical Summaries and Inference.]]></title>
            <link>https://monirah-abdulaziz.medium.com/project-1-local-traffic-statistical-summaries-and-inference-b0c089c27998?source=rss-cac8f1becf29------2</link>
            <guid isPermaLink="false">https://medium.com/p/b0c089c27998</guid>
            <dc:creator><![CDATA[Monirah abdulaziz]]></dc:creator>
            <pubDate>Sat, 02 Jan 2021 12:12:56 GMT</pubDate>
            <atom:updated>2023-06-06T09:06:42.346Z</atom:updated>
            <content:encoded><![CDATA[<h3>Local Traffic, Statistical Summaries and Inference.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*4KKsSeKm3XPUTjGH_PV1Tg.png" /><figcaption>shorturl.at/rPQW1</figcaption></figure><h3>Problem Statment</h3><p>Kingdom of Saudi Arabia (KSA) is the largest country in the Arab states and a member of the “Group of Twenty” (G-20) major world economies. The motor vehicle rate in this country has increased rapidly since the oil boom in the early 1970s, consequently, the number of roads and the transport infrastructures service increased.<br>In Saudi Arabia car is the main means of transportation, it provides the flexibility and freedom that people really value and want. Road traffic accidents are one of the most critical public health problems worldwide.<br>The WHO Global Status Report on Road Safety reports that the annual fatality rate per 100,000 people due to traffic accidents in the KSA has increased from 17.4 to 27.4 since the last decade, which is the worst among the countries in the region and is significantly above death rates for other G-20 nations such as the USA, the United Kingdom, Japan, and Australia. The economic losses due to traffic accidents are estimated to be approximately 4.3% of the KSA’s GDP. A study conducted by Turki et al. suggests that more than 19 individuals have lost their lives daily, and approximately 4 people were injured every hour due to road traffic accidents on KSA roads.</p><p>This article takes a look at the number of traffic accidents and driving licenses issued in Saudi Arabia (2016–2017), identifies trends in the data, and combines/analyzes provided datasets with outside research to identify likely factors influencing the outcomes of traffic accidents in the various regions in Saudi Arabia.</p><h3>Datasets</h3><p>In this project, two datasets were provided:</p><ol><li>Driving Licenses: <br>This dataset contains Saudi Arabia Driving Licenses Issued By Administrative Areas from 1993–2016.<a href="https://datasource.kapsarc.org/explore/dataset/saudi-arabia-driving-licenses-issued-in-the-kingdom-2004-2008/information/?disjunctive.administritive_area&amp;sort=time_period&amp;location=5,24.37495,45.08024&amp;basemap=jawg.streets"> Data from the General Authority for Statistics.</a></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UQWTWoO9KtaNCMMoc3bayw.png" /></figure><p>2. Traffic Accidents and Casualties<br>This dataset contains Saudi Arabia Traffic Accidents and Casualties by Region for 2016-2017. <a href="https://datasource.kapsarc.org/explore/dataset/saudi-arabia-traffic-accidents-and-casualties-injured-dead-2008/export/?disjunctive.region&amp;disjunctive.indicator&amp;sort=time_period">Data from the General Authority for Statistics.</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tME3iXcYe0CGxzqqyhqpVg.png" /></figure><h3><strong>Data Import &amp; Cleaning</strong></h3><p>Identify, diagnose, and treat a variety of dirty data and forming it into an appropriate form for the statistical analysis.</p><p>This what the data looked like after the cleaning process:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/778/1*QKUD4U0lTcmAxw_sPej80w.png" /><figcaption>merged cleaned dataframe.</figcaption></figure><h3><strong>Exploratory Data Analysis</strong></h3><p>To give a quick overview of each numeric feature.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*8e6xzx8H17xW7znEXXUmSQ.png" /></figure><h3>Visualize the data</h3><p>Visualizing the data allows us to quickly convey the findings (even for a non-technical audience), it will often reveal trends in data that escaped when we were looking only at numbers.</p><p><strong>Some plots used in this project:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*6cK3e5ac-nd4FO0Mk0_iIA.png" /></figure><p>The above heatmap illustrated the strong correlation between accident cases and death and injury cases, which means accidents usually lead to others, and the injury cases lead to death cases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_WcbyiI4o6XjoSAy52LnDA.png" /></figure><p>Histogram is a representation of the distribution of numerical data, all above histograms are right-skewed histogram that has a peak that is left of center and a more gradual tapering to the right side of the graph. This is a unimodal data set, with the mode closer to the left of the graph and smaller than either the mean or the median. The mean of right-skewed data is to the right of the peak and it is a greater value than either the median or the mode. This shape indicates that there are a number of data points, perhaps outliers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/882/1*S647DwuaDLM5eurAfrs5vQ.png" /></figure><p>Car accidents in 2016 and 2017 killed more than 16500 people, causing over 80,000 injuries. The most deadly accidents happened in Makkah (3884 death cases), followed by Riyadh (2829 death cases), then the Eastern region (2076 death cases), while the minimum numbers of deadly accidents were in Northern Border (305 death cases), Al-Baha (319 death cases), and Najran (367 death cases).</p><p>The most injured accidents happened in Makkah (23006 injured cases) which is a very high number comparing to other regions, followed by the Eastern region (8966 injured cases), then Riyadh (8747 injured cases) while the minimum numbers of the injured cases were in Northern Border (1005 injured case), followed by Najran (1472 injured cases), then Hail (1705 injured cases).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VqCXW7ZxAPV3POBqzwmgKA.png" /></figure><p>A scatter plot is a type of plot to display values for typically two variables for a set of data. This scatterplot illustrates the traffic accidents for 2016 vs 2017, the total number of accidents in 2017 is 13.6% less than in 2016, the maximum number of accidents in 2016 was in Riyadh, while the maximum number of accidents in 2017 was in Makkah. Najran and Al-Baha are the lowest in both years.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rRY-VYZZlDd67eIW8NA7rA.png" /></figure><p>A boxplot is a standardized way of displaying the distribution of data based on a five-number summary (“minimum”, first quartile (Q1), median, third quartile (Q3), and “maximum”).</p><p>The above boxplot illustrates the central tendency and spread in both dead and injured variables, there are some outliers shown, the highest outlier in the dead boxplot represents the number of death cases occurred in Makkah (2243 death cases), while the highest one in the injured boxplot represents the number of injury cases that occurred in Makkah (12383 injured cases) followed by the next one which is also in Makkah (10623 cases)</p><h3>Descriptive and Inferential Statistics</h3><p>Descriptive statistics describe data (for example, a chart or graph) and inferential statistics allows to make predictions (“inferences”) from that data. With inferential statistics, we take data from samples and make generalizations about a population.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EBjil52ihpI8UZoqDuzOmw.png" /></figure><p>The above histogram shows that the driving license is positively skewed, A positive-skewed distribution is one whose right tail is longer or fatter than its left, When a distribution is positively skewed, the mean is greater than the median, which is greater than the mode.<br> <em>Positive skew: mode &lt; median &lt; mean</em></p><p>Although the distribution is not normal in previous variables, The central limit theorem (CLT) is a theorem that gives us a way to turn a non-normal distribution into a normal distribution. It tells us that, even if a population distribution is non-normal, its sampling distribution of the sample mean will be normal for a large number of samples (at least 30).</p><h3>Investigate trends in the data</h3><p>This section examines the scientific data, to see the overall trend of driving licenses based on years (1993–2017) and traffic accidents numbers for years (2016–2017)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/399/1*1YoCRAWfk9ZDgdAd06s-gQ.png" /></figure><p>Riyadh got the first four places in terms of the number of driving licenses issued during (1993–2017) followed by Makkah.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*PTMkHfx9KRruo8PWMGbdoQ.png" /></figure><p>In terms of the number of driving licenses issued during (1993–2017), Tabouk and Al-Baha get the lowest places by 915, 997 respectively.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/771/1*u2lX_T6pun8SAN9zvfZQBQ.png" /></figure><p>The above is a part of the table that shows the regions that have more Driving Licenses issued each year than the year average, During 1993–2017, Al-Qaseem -5 years-, Makkah -each year-, Riyadh -21 years-, Eastern -21 years-, Assir and Hail -one year-, these are the regions that have more driving licenses issued in each year than the year average. Makkah, Riyadh, Eastern, and Al-Qaseem, these administrative regions are the most populous. The slightly higher than mean in driving licenses in Hail happened in 2016, and In Assir happened in 2015.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/569/1*elFaoUAVfaHvKvGUsoEpvA.png" /></figure><p>The above table shows the regions that have more driving accidents occurred in each year than the yearly average during 2016–2017. The highest number of accidents was in Makkah: 145,541 accident happened in 2017, followed by Riyadh 141736 accidents happened in 2016.</p><h3>Outside Research</h3><p>Doing outside research on provincial and central policies that might influence the trends in the number of driving licenses and traffic accident rates. The data is borrowed from the <a href="https://www.stats.gov.sa/">General Authority for Statistics</a> and the <a href="https://www.gccstat.org/images/gccstat/docman/publications/116-gcc-accidents-statistics.pdf">Statistical Centre for the GCC</a>.</p><h4>1. Vision 2030<br>In fact, various preventive measures have been effectively adapted to reduce the burden of traffic accidents in Saudi Arabia, the Ministry of the Interior (MoI) has set a strong strategy to reduce traffic accidents as part of the government’s Vision 2030 program.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uZaMd0JW9n4V9dBg6pF4Mw.png" /></figure><p>As shown in the above plot, the number of total accidents dropped from over 460000 accidents in 2017 to 287781 accidents in 2019, The ratio down almost 38% percent.</p><h4><strong>2. </strong>Increase the demand for driving licenses</h4><p>As shown in the below plot, the number of total driving license is getting higher, it raised from 928165 licenses in 2017 to 1026569 licenses in 2019, The ratio up 10.6% percent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VG5ssDUYusU9k69KUBsVew.png" /></figure><h4><strong>3.The development of the number of death cases in the GCC countries</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iHdyFXpb5E57y2ydEqhHGw.png" /></figure><p>As shown in the above plot, the GCC occupied the penultimate position, followed by Malaysia. While Japan, Australia, and UE were at the forefront at the lowest traffic accident mortality rate.</p><p><strong>Some policies and engineering measures in these leading countries in an attempt to understand the reasons behind their good performance:</strong></p><ul><li><strong>ROAD SAFETY POLICIES:</strong></li></ul><p>The Traffic Safety Policies Law in Japan requires the government to report to the Diet, each year, on the status of traffic crashes, on measures being implemented and on plans for traffic safety measures. This is contained in the <em>‘White paper on traffic safety in Japan</em>’:<br> -The aim is a crash-free society.<br> -Dealing with the issue of human error in public transportation: by improving the organizational structures and systems of companies providing transport services.<br> -Encourage participatory traffic safety activities by enabling citizens to participate in the planning stages of traffic safety measures run by national and local authorities.</p><ul><li><strong>MEASURES TO IMPROVE THE ROAD TRAFFIC ENVIRONMENT</strong></li></ul><p><em>The White Paper A New Deal for Transport: Better for Everyone in the UK</em> made it clear that merely building more new roads is not the answer. The emphasis is now on making the best use of the existing network, giving priority to treating the places with the worst safety, congestion, and environmental records. Key elements of the approach include recognition that good engineering reduces the risk of accidents.</p><h3>Key takeaways and recommendations</h3><p>Rapid development, increased number of vehicles together with population growth, are all contributing to a rise in the number of road accidents, injuries, and fatalities. Although road safety remains a low priority for most governments in the developing world, there is a growing awareness of the social, economic, and public health problems caused by traffic accidents.</p><ul><li>The number of total accidents is getting lower, it dropped from over 460000 in 2017 to 287781 in 2019, The ratio down almost 38% percent, through the National Transformation Program and the Kingdom’s Vision 2030, with the participation of relevant sectors, which contributes to unifying efforts and speed of achievement.</li><li>The number of total driving license is getting higher, it raised from 928165 in 2017 to 1026569 in 2019, The ratio up 10.6% percent. the relationship between the number of licenses and the population is a positive correlation, in addition to allowing women to drive a car. On 26 September 2017, King Salman issued an order to allow women to drive in Saudi Arabia.</li></ul><h4>Recommendations</h4><ul><li>Assess the problem, policies, and institutional settings relating to road traffic injury and the capacity for road traffic injury prevention in each region.</li><li>Specific actions are needed to prevent road traffic crashes and to minimize their consequences. These actions should be based on sound evidence and analysis of road traffic injuries, be culturally appropriate and tested locally, and form part of the national strategy to address the problem of road accidents, especially in cities that had the most accidents and deaths: Makkah, Riyadh, and Eastern province.</li></ul><h3>Additional Data</h3><ul><li><strong>Driver age in each accident.</strong></li><li><strong>Explain the causes of each accident:<br> —</strong> human factors/personnel error.<br> — malfunction or failure of vehicle structures or other systems.<br> — deficient maintenance.<br> — hazardous environment involving weather, animal, birds, etc.</li><li><strong>Drive a vehicle without a valid driver’s license or not.</strong></li><li><strong>Driving under the influence (DUI) or not.</strong></li></ul><h3>References</h3><p>amal, A.; Rahman, M.T.; Al-Ahmadi, H.M.; Mansoor, U. The Dilemma of Road Safety in the Eastern Province of Saudi Arabia: Consequences and Prevention Strategies. Int. J. Environ. Res. Public Health 2020, 17, 157</p><p><a href="https://discuss.analyticsvidhya.com/t/difference-between-wide-and-long-data-format/8110/2">https://discuss.analyticsvidhya.com/t/difference-between-wide-and-long-data-format/8110/2</a></p><p><a href="https://www.stats.gov.sa/6370">https://www.stats.gov.sa/6370</a></p><p><a href="https://taifchamber.org.sa/news_details/621/7-%D8%A3%D8%B3%D8%A8%D8%A7%D8%A8-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-%D8%A7%D9%84%D9%85%D8%B1%D9%88%D8%B1%D9%8A%D8%A9-%D8%B9%D9%84%D9%89-%D8%B7%D8%B1%D9%8A%D9%82-%D8%A7%D9%84%D8%AC%D9%86%D9%88%D8%A8-%D8%A8%D9%80-%D8%A7%D9%84%D8%B7%D8%A7%D8%A6%D9%81">https://taifchamber.org.sa/news_details/621/7-%D8%A3%D8%B3%D8%A8%D8%A7%D8%A8-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-%D8%A7%D9%84%D9%85%D8%B1%D9%88%D8%B1%D9%8A%D8%A9-%D8%B9%D9%84%D9%89-%D8%B7%D8%B1%D9%8A%D9%82-%D8%A7%D9%84%D8%AC%D9%86%D9%88%D8%A8-%D8%A8%D9%80-%D8%A7%D9%84%D8%B7%D8%A7%D8%A6%D9%81</a></p><p><a href="https://www.moi.gov.sa/wps/portal/Home/sectors/publicsecurity/traffic/contents/!ut/p/z0/04_Sj9CPykssy0xPLMnMz0vMAfIjo8ziDTxNTDwMTYy83V0CTQ0cA71d_T1djI0MXA30gxOL9L30o_ArApqSmVVYGOWoH5Wcn1eSWlGiH1FSlJiWlpmsagBlKCQWqRrkJmbmqRqUZebngB2gUJAKdERJZmqxfkG2ezgAhzhSyw!!/">https://www.moi.gov.sa/wps/portal/Home/sectors/publicsecurity/traffic/contents/!ut/p/z0/04_Sj9CPykssy0xPLMnMz0vMAfIjo8ziDTxNTDwMTYy83V0CTQ0cA71d_T1djI0MXA30gxOL9L30o_ArApqSmVVYGOWoH5Wcn1eSWlGiH1FSlJiWlpmsagBlKCQWqRrkJmbmqRqUZebngB2gUJAKdERJZmqxfkG2ezgAhzhSyw!!/</a></p><p><a href="https://www.stats.gov.sa/ar/1020">https://www.stats.gov.sa/ar/1020</a></p><p><a href="https://www.stats.gov.sa/ar/2">https://www.stats.gov.sa/ar/2</a></p><p><a href="https://www.gccstat.org/images/gccstat/docman/publications/116-gcc-accidents-statistics.pdf">https://www.gccstat.org/images/gccstat/docman/publications/116-gcc-accidents-statistics.pdf</a></p><p><a href="https://www.codatu.org/wp-content/uploads/Road-safety-in-five-leading-countries-Rifaat-SHOUKRALLAH.pdf">https://www.codatu.org/wp-content/uploads/Road-safety-in-five-leading-countries-Rifaat-SHOUKRALLAH.pdf</a><br> <br> <br><a href="https://www.alj.com/en/perspective/women-at-the-wheel-whats-changed-in-saudi-arabia/">https://www.alj.com/en/perspective/women-at-the-wheel-whats-changed-in-saudi-arabia/</a><br> <br>- <a href="https://www.statisticshowto.com/inferential-statistics/#:~:text=Descriptive%20statistics%20describes%20data%20(for,make%20generalizations%20about%20a%20population.">https://www.statisticshowto.com/inferential-statistics/#:~:text=Descriptive%20statistics%20describes%20data%20(for,make%20generalizations%20about%20a%20population.</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b0c089c27998" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>