<jupyter_start><jupyter_text>Introductory applied machine learning (INFR10069)  Assignment 1: Data analysis and visualisation  Marking Breakdown**70-100%** results/answer correct plus extra achievement at understanding or analysis of results. Clear explanations, evidence of creative or deeper thought will contribute to a higher grade.**60-69%** results/answer correct or nearly correct and well explained.**50-59%** results/answer in right direction but significant errors.**40-49%** some evidence that the student has gained some understanding, but not answered the questionsproperly.**0-39%** serious error or slack work.  MechanicsFill out this notebook, save it, and **submit it electronically as described below.**On a DICE environment, open the terminal, navigate to the location of this notebook, and submit this notebook file using the following command:`submit iaml cw1 03_Assignment_1.ipynb`What actually happens in the background is that your file is placed in a folder available to markers. If you submit a file with the same name into the same location, **it will *overwrite* your previous submission**. You can check the status of your submissions with the `show_submissions` command.**Distance Learners:** To copy your work up to DICE (such that you can use the `submit` command) you can use `scp` or `rsync` (you may need to install these yourself). You can copy files up using `student.ssh.inf.ed.ac.uk`, then ssh in to submit, e.g. (in a unix terminal):```filename=03_Assignment_1.ipynblocal_scp_filepath=~/git/iaml2017/${filename}UUN=s0816700server_address=student.ssh.inf.ed.ac.ukscp -r ${local_scp_filepath} ${UUN}@${server_address}:${filename} rsync -rl ${local_scp_filepath} ${UUN}@${server_address}:${filename}ssh ${UUN}@${server_address}ssh student.loginsubmit iaml cw1 03_Assignment_1.ipynb```**Late submissions:** The policy stated in the School of Informatics MSc Degree Guide is that normally you will not be allowed to submit coursework late. See http://www.inf.ed.ac.uk/teaching/years/msc/courseguide10.htmlexam for exceptions to this, e.g. in case of serious medical illness or serious personal problems.**Collaboration:** You may discuss the assignment with your colleagues, provided that the writing that you submit is entirely your own. That is, you should NOT borrow actual text or code from other students. We ask that you provide a list of the people who you've had discussions with (if any).**Resubmission:** If you submit your file again, the previous submission is **overwritten**. We will mark the version that is in the submission folder at the deadline.  Important Instructions1. You *MUST* have your environment set up as in the [README](https://github.com/JamesOwers/iaml2017) and you *must activate this environment before running this notebook*:```source activate iamlcd iaml_2017jupyter notebook Navigate to this file```1. Wherever you are required to produce code you should use code cells, otherwise you should use markdown cells to report results and explain answers.1. The .csv files that you will be using are located at `./datasets` (the `datasets` directory is adjacent to this file).1. **IMPORTANT:** Keep your answers brief and concise. Most written questions can be answered with 2-3 lines of explanation.  ImportsExecute the cell below to import all packages you will be using in the rest of the assignemnt.<jupyter_code>from __future__ import print_function, division
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn as sklearn
import seaborn as sns
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Description of the datasetThis assignment is based on the 20 Newsgroups Dataset. This dataset is a collection of approximately 20,000 newsgroup documents, partitioned (nearly) evenly across 20 different newsgroups, each corresponding to a different topic. Some of the newsgroups are very closely related to each other (e.g. comp.sys.ibm.pc.hardware, comp.sys.mac.hardware), while others are highly unrelated (e.g misc.forsale, soc.religion.christian). There are three versions of the 20 Newsgroups Dataset. In this assignment we will use the `bydate` matlab version in which documents are sorted by date into training (60%) and test (40%) sets, newsgroup-identifying headers are dropped and duplicates are removed. This collection comprises roughly 61,000 different words, which results in a bag-of-words representation with frequency counts. More specifically, each document is represented by a 61,000 dimensional vector that contains the counts for each of the 61,000 different words present in the respective document. To save you time and to make the problem manageable with limited computational resources, we preprocessed the original dataset. We will use documents from only 5 out of the 20 newsgroups, which results in a 5-class problem. More specifically the 5 classes correspond to the following newsgroups: 1. `alt.atheism`2. `comp.sys.ibm.pc.hardware`3. `comp.sys.mac.hardware`4. `rec.sport.baseball`5. `rec.sport.hockey `However, note here that classes 2-3 and 4-5 are rather closely related. Additionally, we computed the [mutual information](https://en.wikipedia.org/wiki/Mutual_information) of each word with the class attribute and selected the 520 words out of 61,000 that had highest mutual information. Therefore, our dataset is a $N \times 520$ dimensional matrix, where $N$ is the number of documents. For very sophisticated technical reasons 1 was added to all the word counts in part A. The resulting representation is much more compact and can be used directly to perform our experiments in Python.  1. Exploration of the dataset [40%] Your first task is to get a feel for the data that you will be dealing with in the rest of the assignment.  ========== Question 1.1 --- [5 marks] ==========Load the datasets `train_20news_partA.csv` and `train_20news_partB.csv` into two separate pandas DataFrames.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.2 --- [3 marks] ==========Display basic information for dataset A such as number of columns, type, and memory usage (*hint: pandas dataframes have a built in method for this*)<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.3 --- [3 marks] ==========How many data points and how many attributes are there in the dataset that we can use to model the target variable `class`? *Your answer goes here*  ========== Question 1.4 --- [3 marks] ==========Use a Pandas method to display the summary statistics for the `news_A` DataFrame.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.5 --- [3 marks] ==========Display the first 7 instances of dataset A.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.6 --- [5 marks] ==========Display the names of the first 100 attributes in dataset A. You might observe that each attribute consists of two parts:1. `w_` (where x is an index corresponding to each word)2. the actual name of the word<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.7 --- [4 marks] ==========Familiarise yourself with the [`stripplot`](https://seaborn.github.io/generated/seaborn.stripplot.html?highlight=stripplotseaborn.stripplot) function in `seaborn`. Pick one attribute of your choice (except `class`) and display a stripplot for that attribute for dataset A. Demonstrate the distribution of the data separately for each class (by making appropriate use of the `x` argument in `stripplot`). Set the `jitter` argument to `True` and the `alpha` argument to an appropriate value (to add transparency). When the jitter parameter is enabled a small amount of noise is added to the data so that there is less overlap and the distribution is easier to visualise.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.8 --- [4 marks] ==========The stripplot illustrates the distribution of a single attribute. We can also visualise the joint distribution of two variables by using a scatter plot. Again, we want to add a bit of noise into the data so that is easier to see which parts of the space (2-dimensional in our case) have larger probability densities. For this, you will be using the function `scatter_jitter` provided below. This function takes as input two numpy arrays containing the features of interest. Pick two attributes of your choice from dataset A and use the provided function to plot their joint distribution. You can play around with the amount of noise added by tweaking the `jitter` parameter. Alternatively, you can just use its default value which is set to 0.2.<jupyter_code>def scatter_jitter(arr1, arr2, jitter=0.2):
    """ Plots a joint scatter plot of two arrays by adding small noise to each example. 
    Noise is proportional to variance in each dimension. """
    arr1 = np.asarray(arr1)
    arr2 = np.asarray(arr2)
    arr1 = arr1 + jitter*arr1.std(axis=0)*np.random.standard_normal(arr1.shape)
    arr2 = arr2 + jitter*arr2.std(axis=0)*np.random.standard_normal(arr2.shape)
    plt.scatter(arr1, arr2, marker=4)
# Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.9 --- [7 marks] ==========From the strip and scatter plots above you might observe that there is something peculiar about the data. Indeed most attributes take very small values (usually in the range 1-10) but there are some data points (i.e. rows) in the dataset where the attributes take very large values. These data points are called [outliers](https://en.wikipedia.org/wiki/Outlier).You might think that the presence of outliers in the dataset has been a resut of noise contamination (you wouldn't expect the same word to appear 600 times within an e-mail, would you?). Your job now is to create a new dataset from dataset A (name it `news_A_clean`) and remove the outliers. Create some metric to find the outliers and check that your metric is reasonable. Be careful not to alter the original `news_A`...we may require it in its dirty format later...<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 1.10 --- [3 marks] ==========Write code to return the number of data points in the clean dataset, and the number of documents that have been excluded as outliers<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>2. Naive Bayes classification [60%]Now we want to fit a Gaussian Naive Bayes model to the cleaned dataset A. You might want first to familiarise yourself with the [`GaussianNB`](http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html) class in `Sklearn`.  ========== Question 2.1 --- [4 marks] ==========By using the `scatter_jitter` function provided above, display a scatter plot of the features `w281_ico` and `w273_tek` for the cleaned dataset A. Set the jitter value to something small (e.g. 0.1). Label axes appropriately.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.2 --- [6 marks] ==========What do you observe? How does that relate to the Naive Bayes assumption? What would be the main issue we would have to face if we didn't make this assumption? *Your answer goes here*  ========== Question 2.3 --- [5 marks] ==========Fit a Gaussian Naive Bayes model to the cleaned dataset A. Your input features should be all the attributes in the dataset except the `class` attribute which will be your target. Display the classification accuracy on the training dataset.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.4 --- [5 marks] ==========Plot the (normalised) confusion matrix for the training data. Label axes appropriately.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.5 --- [3 marks] ==========Comment on the confusion matrix from the previous question. Does it look like what you would have expected? Explain. *Your answer goes here*  ========== Question 2.6 --- [5 marks] ==========Fit a Gaussian Naive Bayes model to the original dataset A (including the outliers). Display the classification accuracy on the training dataset.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.7 --- [4 marks] ==========Comment on the above results (Questions 2.3 & 2.6). In particular explain why you think that cleaning the data helps in this case. *Your answer goes here*  ========== Question 2.8 --- [5 marks] ==========Now we want to evaluate the generalisation of the classifier on new (i.e. unseen data). Use the classifier you trained in Question 2.5 (i.e. on the cleaned dataset) and test its performance on dataset `train_20news_partB`. Display the (normalized) confusion matrix and the classification accuracy on the Dataset B.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.9 --- [4 marks] ==========Comment on the results from the previous question. Do you think this is an acceptable level of performance? Which are the easiest and most difficult classes to predict correctly?  *Your answer goes here*  ========== Question 2.10 --- [4 marks] ==========What is a reasonable baseline against which to compare the classiffication performance? *Hint: What is the simplest classiffier you can think of and what would its performance be on this dataset?*  *Your answer goes here*  ========== Question 2.11 --- [4 marks] ==========Estimate the baseline performance.<jupyter_code># Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.12 --- [3 marks] ==========Execute the cell below to get the prediction on the test dataset by using a different classifier which we will be introducing in this class later on. By using this prediction provided below (`rf_prediction`) plot the confusion matrix and display the classification accuracy on the test dataset. *Important: Make sure the test dataset is loaded in a DataFrame called `news_B` otherwise execution will return an error. In that case replace the DataFrame name in the third line.*<jupyter_code>from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators = 50).fit(X=news_A_clean.drop("class", axis=1), y=news_A_clean["class"])
X_ts = news_B.drop('class', axis=1)
rf_prediction = rf.predict(X=X_ts)
# Your code goes here<jupyter_output><empty_output><jupyter_text>========== Question 2.13 --- [8 marks] ==========Which classifier (Naive Bayes or Random Forest) would you trust if you had to choose? What are the reasons you believe the Gaussian Naive Bayes classifier does not perofm so well in this particular problem? You are not expected to justify the performance level achieved by the Random Forest classifier. Feel free to use code and plots to illustrate your points. *Your answer goes here*<jupyter_code># Your code goes here<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09812218989685269, 'fraction_numerical': 0.017191219254165564, 'mean_word_length': 5.257757550682665, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 73, 'https://': 4, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '452081', 'license': 'MIT', 'n_tokens_mistral': 4155, 'n_tokens_neox': 3881, 'n_words': 1974, 'path': '03_Assignment_1.ipynb', 'repo_name': 'CaesarZhang070497/Iaml', 'size': '15124'}