<jupyter_start><jupyter_text>Predicting sentiment from product reviewsIn this notebook, you will use product review data from Amazon.com to predict whether the sentiments about a product (from its reviews) are positive or negative.* Use DataFrames to do some feature engineering* Train a logistic regression model to predict the sentiment of product reviews.* Inspect the weights (coefficients) of a trained logistic regression model.* Make a prediction (both class and probability) of sentiment for a new product review.* Given the logistic regression weights, predictors and ground truth labels, write a function to compute the **accuracy** of the model.* Inspect the coefficients of the logistic regression model and interpret their meanings.* Compare multiple logistic regression models.  Importing Libraries<jupyter_code>import os
import zipfile
import string
import numpy as np
import pandas as pd
from sklearn import linear_model
from sklearn.feature_extraction.text import CountVectorizer
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Unzipping files with Amazon Baby Products Reviews The dataset consists of baby product reviews from Amazon.com.<jupyter_code># Put files in current direction into a list
files_list = [f for f in os.listdir('.') if os.path.isfile(f)]
# Filename of unzipped file
unzipped_file = 'amazon_baby.csv'
# If upzipped file not in files_list, unzip the file
if unzipped_file not in files_list:
    zip_file = unzipped_file + '.zip'
    unzipping = zipfile.ZipFile(zip_file)
    unzipping.extractall()
    unzipping.close<jupyter_output><empty_output><jupyter_text>Loading the products data The dataset is loaded into a Pandas DataFrame called products.<jupyter_code>products = pd.read_csv("amazon_baby.csv")<jupyter_output><empty_output><jupyter_text>Now, let us see a preview of what the dataset looks like.<jupyter_code>products.head()<jupyter_output><empty_output><jupyter_text>Performing text cleaning Let us explore a specific example of a baby product.<jupyter_code>products.ix[1]<jupyter_output><empty_output><jupyter_text>Now, we will perform 2 simple data transformations:1. Remove punctuation using [Python's built-in](https://docs.python.org/2/library/string.html) string functionality.2. Transform the reviews into word-counts.**Aside**. In this notebook, we remove all punctuations for the sake of simplicity. A smarter approach to punctuations would preserve phrases such as "I'd", "would've", "hadn't" and so forth. See [this page](https://www.cis.upenn.edu/~treebank/tokenization.html) for an example of smart handling of punctuations. Before removing the punctuation from the strings in the review column, we will fall all NA values with empty string.<jupyter_code>products["review"] = products["review"].fillna("")<jupyter_output><empty_output><jupyter_text>Below, we are removing all the punctuation from the strings in the review column and saving the result into a new column in the dataframe.<jupyter_code>products["review_clean"] = products["review"].str.translate(None, string.punctuation)<jupyter_output><empty_output><jupyter_text>Extract sentimentsWe will **ignore** all reviews with *rating = 3*, since they tend to have a neutral sentiment.<jupyter_code>products = products[products['rating'] != 3]
len(products)<jupyter_output><empty_output><jupyter_text>Now, we will assign reviews with a rating of 4 or higher to be *positive* reviews, while the ones with rating of 2 or lower are *negative*. For the sentiment column, we use +1 for the positive class label and -1 for the negative class label. Below, we are create a function we will applyi to the "ratings" column of the dataframe to determine if the review is positive or negative.<jupyter_code>def sent_func(x):
    # If rating is >=4, return a positive sentiment (+1)
    if x>=4:
        return 1
    # Else, return a negative sentiment (-1)
    else:
        return -1<jupyter_output><empty_output><jupyter_text>Creating a "sentiment" column by applying the sent_func to the "rating" column in the dataframe.<jupyter_code>products['sentiment'] = products['rating'].apply(sent_func)
products.ix[20:22]<jupyter_output><empty_output><jupyter_text>Now, we can see that the dataset contains an extra column called **sentiment** which is either positive (+1) or negative (-1).  Split data into training and test sets Let's perform a train/test split with 80% of the data in the training set and 20% of the data in the test set. Loading the indicies for the train and test data and putting them in a list<jupyter_code>with open('module-2-assignment-train-idx.txt', 'r') as train_file:
    ind_list_train = map(int,train_file.read().split(','))    
with open('module-2-assignment-test-idx.txt', 'r') as test_file:
    ind_list_test = map(int,test_file.read().split(','))<jupyter_output><empty_output><jupyter_text>Using the indicies of the train and test data to create the train and test datasets.<jupyter_code>train_data = products.iloc[ind_list_train,:]
test_data = products.iloc[ind_list_test,:]
print len(train_data)
print len(test_data)<jupyter_output>133416
33336<jupyter_text>Build the word count vector for each review We will now compute the word count for each word that appears in the reviews. A vector consisting of word counts is often referred to as bag-of-word features. Since most words occur in only a few reviews, word count vectors are sparse. For this reason, scikit-learn and many other tools use sparse matrices to store a collection of word count vectors. Refer to appropriate manuals to produce sparse word count vectors. General steps for extracting word count vectors are as follows: - Learn a vocabulary (set of all words) from the training data. Only the words that show up in the training data will be considered for feature extraction.- Compute the occurrences of the words in each review and collect them into a row vector.- Build a sparse matrix where each row is the word count vector for the corresponding review. Call this matrix train_matrix.- Using the same mapping between words and columns, convert the test data into a sparse matrix test_matrix. The following cell uses CountVectorizer in scikit-learn. Notice the token_pattern argument in the constructor.<jupyter_code># Use this token pattern to keep single-letter words
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
# First, learn vocabulary from the training data and assign columns to words
# Then convert the training data into a sparse matrix
train_matrix = vectorizer.fit_transform(train_data['review_clean'])
# Second, convert the test data into a sparse matrix, using the same word-column mapping
test_matrix = vectorizer.transform(test_data['review_clean'])<jupyter_output><empty_output><jupyter_text>Train a sentiment classifier with logistic regressionWe will now use logistic regression to create a sentiment classifier on the training data. This model will use the column **word_count** as a feature and the column **sentiment** as the target.**Note:** This line may take 1-2 minutes. Creating an instance of the LogisticRegression class<jupyter_code>logreg = linear_model.LogisticRegression()<jupyter_output><empty_output><jupyter_text>Using the fit method to train the classifier. This model should use the sparse word count matrix (*train_matrix*) as features and the column sentiment of *train_data* as the target. Use the default values for other parameters. Call this model *sentiment_model*.<jupyter_code>sentiment_model = logreg.fit(train_matrix, train_data["sentiment"])<jupyter_output><empty_output><jupyter_text>Putting all the weights from the model into a numpy array.<jupyter_code>weights_list = list(sentiment_model.intercept_) + list(sentiment_model.coef_.flatten())
weights_sent_model = np.array(weights_list, dtype = np.double)
print len(weights_sent_model)<jupyter_output>121713<jupyter_text>There are a total of `121713` coefficients in the model. Recall from the lecture that positive weights $w_j$ correspond to weights that cause positive sentiment, while negative weights correspond to negative sentiment.  **Quiz question:** How many weights are >= 0?<jupyter_code>num_positive_weights = len(weights_sent_model[weights_sent_model >= 0.0])
num_negative_weights = len(weights_sent_model[weights_sent_model < 0.0])

print "Number of positive weights: %i" % num_positive_weights
print "Number of negative weights: %i" % num_negative_weights<jupyter_output>Number of positive weights: 85915
Number of negative weights: 35798<jupyter_text>Making predictions with logistic regressionNow that a model is trained, we can make predictions on the **test data**. In this section, we will explore this in the context of 3 examples in the test dataset.  We refer to this set of 3 examples as the **sample_test_data**.<jupyter_code>sample_test_data = test_data.ix[[59,71,91]]
print sample_test_data['rating']
sample_test_data<jupyter_output>59    5
71    2
91    1
Name: rating, dtype: int64<jupyter_text>Let's dig deeper into the first row of the **sample_test_data**. Here's the full review:<jupyter_code>sample_test_data['review'].ix[59]<jupyter_output><empty_output><jupyter_text>That review seems pretty positive.Now, let's see what the next row of the **sample_test_data** looks like. As we could guess from the sentiment (-1), the review is quite negative.<jupyter_code>sample_test_data['review'].ix[71]<jupyter_output><empty_output><jupyter_text>We will now make a **class** prediction for the **sample_test_data**. The `sentiment_model` should predict **+1** if the sentiment is positive and **-1** if the sentiment is negative. Recall from the lecture that the **score** (sometimes called **margin**) for the logistic regression model  is defined as:$$\mbox{score}_i = \mathbf{w}^T h(\mathbf{x}_i)$$ where $h(\mathbf{x}_i)$ represents the features for example $i$.  We will write some code to obtain the **scores** . For each row, the **score** (or margin) is a number in the range **[-inf, inf]**.<jupyter_code>sample_test_matrix = vectorizer.transform(sample_test_data['review_clean'])
scores = sentiment_model.decision_function(sample_test_matrix)
print scores<jupyter_output>[  5.61129645  -3.14942405 -10.42641065]<jupyter_text>Predicting sentimentThese scores can be used to make class predictions as follows:$$\hat{y} = \left\{\begin{array}{ll}      +1 & \mathbf{w}^T h(\mathbf{x}_i) > 0 \\      -1 & \mathbf{w}^T h(\mathbf{x}_i) \leq 0 \\\end{array} \right.$$Using scores, write code to calculate $\hat{y}$, the class predictions:<jupyter_code>pred_sent_test_data = []
for val in scores:
    if val>0:
        pred_sent_test_data.append(1)
    else:
        pred_sent_test_data.append(-1)
print pred_sent_test_data<jupyter_output>[1, -1, -1]<jupyter_text>**Checkpoint**: Run the following code to verify that the class predictions obtained by your calculations are the same as that obtained from Scikit-Learn.<jupyter_code>print "Class predictions according to Scikit-Learn:" 
print sentiment_model.predict(sample_test_matrix)<jupyter_output>Class predictions according to Scikit-Learn:
[ 1 -1 -1]<jupyter_text>Probability predictionsRecall from the lectures that we can also calculate the probability predictions from the scores using:$$P(y_i = +1 | \mathbf{x}_i,\mathbf{w}) = \frac{1}{1 + \exp(-\mathbf{w}^T h(\mathbf{x}_i))}.$$Using the variable **scores** calculated previously, write code to calculate the probability that a sentiment is positive using the above formula. For each row, the probabilities should be a number in the range **[0, 1]**.<jupyter_code>prob_pos_score = 1.0/(1.0 + np.exp(-scores))
prob_pos_score<jupyter_output><empty_output><jupyter_text>**Checkpoint**: Make sure your probability predictions match the ones obtained from Scikit-Learn.<jupyter_code>print "Class predictions according to Scikit-Learn:" 
print sentiment_model.predict_proba(sample_test_matrix)[:,1]<jupyter_output>Class predictions according to Scikit-Learn:
[  9.96356994e-01   4.11139780e-02   2.96383837e-05]<jupyter_text>** Quiz Question:** Of the three data points in **sample_test_data**, which one (first, second, or third) has the **lowest probability** of being classified as a positive review? ** The 3rd data point has the lowest probability of being positive **  Find the most positive (and negative) review We now turn to examining the full test dataset, **test_data**.Using the `sentiment_model`, find the 40 reviews in the entire **test_data** with the **highest probability** of being classified as a **positive review**. We refer to these as the "most positive reviews."To calculate these top-40 reviews, use the following steps:1.  Make probability predictions on **test_data** using the `sentiment_model`.2.  Sort the data according to those predictions and pick the top 40.  Computing the scores with the sentiment_model decision function and then calculating the probability that y = +1<jupyter_code>scores_test_data = sentiment_model.decision_function(test_matrix)
prob_test_data = 1.0/(1.0 + np.exp(-scores_test_data))<jupyter_output><empty_output><jupyter_text>To find the 40 most positive and the 40 most negative values, we will create a list of tuples with the entries (probability, index). We will then sort the list and will be able to extract the indicies corresponding to each entry.<jupyter_code># List of indicies in the test data
ind_vals_test_data = test_data.index.values
# Empty list that will be filled with the tuples (probability, index)
score_label_lst_test = len(scores_test_data)*[-1]<jupyter_output><empty_output><jupyter_text>Filling the list of tuples with the (probability, index) values<jupyter_code>for i in range(len(scores_test_data)):
    score_label_lst_test[i] = (prob_test_data[i],ind_vals_test_data[i])<jupyter_output><empty_output><jupyter_text>Sorting the list with the entries (probability, index)<jupyter_code>score_label_lst_test.sort()<jupyter_output><empty_output><jupyter_text>Extracting the top 40 positive reviews and the top 40 negative reviews<jupyter_code>top_40_pos_test_rev = score_label_lst_test[-40:]
top_40_neg_test_rev = score_label_lst_test[0:40]<jupyter_output><empty_output><jupyter_text>Getting the indicies of the top 40 positive reviews.<jupyter_code>ind_top_40_pos_test = 40*[-1]
for i,val in enumerate(top_40_pos_test_rev):
    ind_top_40_pos_test[i] = val[1]<jupyter_output><empty_output><jupyter_text>Getting the indicies of the top 40 negative reviews.<jupyter_code>ind_top_40_neg_test = 40*[-1]
for i,val in enumerate(top_40_neg_test_rev):
    ind_top_40_neg_test[i] = val[1]<jupyter_output><empty_output><jupyter_text>**Quiz Question**: Which of the following products are represented in the 40 most positive reviews? [multiple choice]<jupyter_code>test_data.ix[ind_top_40_pos_test]["name"]<jupyter_output><empty_output><jupyter_text>**Quiz Question**: Which of the following products are represented in the 20 most negative reviews?  [multiple choice]<jupyter_code>test_data.ix[ind_top_40_neg_test]["name"]<jupyter_output><empty_output><jupyter_text>Compute accuracy of the classifierWe will now evaluate the accuracy of the trained classifer. Recall that the accuracy is given by$$\mbox{accuracy} = \frac{\mbox{ correctly classified examples}}{\mbox{ total examples}}$$This can be computed as follows:* **Step 1:** Use the trained model to compute class predictions* **Step 2:** Count the number of data points when the predicted class labels match the ground truth labels (called `true_labels` below).* **Step 3:** Divide the total number of correct predictions by the total number of data points in the dataset.Complete the function below to compute the classification accuracy:<jupyter_code>def get_classification_accuracy(model, data, true_labels):
    
    # Constructing the wordcount vector
    data_matrix = vectorizer.transform(data['review_clean'])
    
    # Getting the predictions
    preds_data = model.predict(data_matrix)
    
    # Computing the number of correctly classified examples and the total examples
    n_correct = float(np.sum(preds_data == true_labels.values))
    n_total = float(len(preds_data))

    # Computing the accuracy by dividing number of 
    #correctly classified examples by total number of examples
    accuracy = n_correct/n_total
    
    return accuracy<jupyter_output><empty_output><jupyter_text>Now, let's compute the classification accuracy of the **sentiment_model** on the **test_data**.<jupyter_code>acc_sent_mod_test = get_classification_accuracy(sentiment_model, test_data, test_data['sentiment'])
print acc_sent_mod_test<jupyter_output>0.932145428366<jupyter_text>**Quiz Question**: What is the accuracy of the **sentiment_model** on the **test_data**? Round your answer to 2 decimal places (e.g. 0.76).<jupyter_code>print "Accuracy on Test Data: %.2f" %(acc_sent_mod_test)<jupyter_output>Accuracy on Test Data: 0.93<jupyter_text>**Quiz Question**: Does a higher accuracy value on the **training_data** always imply that the classifier is better? ** No, you may be overfitting. ** Now, computing the accuracy of the sentiment model on the training data for a future quiz question.<jupyter_code>acc_sent_mod_train = get_classification_accuracy(sentiment_model, train_data, train_data['sentiment'])
print acc_sent_mod_train<jupyter_output>0.96789740361<jupyter_text>Finding the weights of significant words for the sentiment_model. In this section, we will find the weights of significant words for the sentiment_model. Creating a vocab list. The vocab list constains all the words used for the sentiment_model<jupyter_code>vocab = vectorizer.get_feature_names()
print len(vocab)<jupyter_output>121712<jupyter_text>Creating a list of the significant words in the utf-8 format<jupyter_code>un_sig_words = [u'love', u'great', u'easy', u'old', u'little', u'perfect', u'loves', 
                u'well', u'able', u'car', u'broke', u'less', u'even', u'waste', u'disappointed', 
                u'work', u'product', u'money', u'would', u'return']<jupyter_output><empty_output><jupyter_text>Creating a list that will store all the indicies where the significant words appear in the vocab list.<jupyter_code>ind_vocab_sig_words = []<jupyter_output><empty_output><jupyter_text>Finding the index where each significant word appears.<jupyter_code>for word in un_sig_words:
    ind_vocab_sig_words.append(vocab.index(word))<jupyter_output><empty_output><jupyter_text>Creating an empty list that will store the weights of the significant words. Then, using the index to find the weight for each signigicant word.<jupyter_code>ws_sent_mod_sig_words = []
for ind in ind_vocab_sig_words:
    ws_sent_mod_sig_words.append(sentiment_model.coef_.flatten()[ind])<jupyter_output><empty_output><jupyter_text>Creating a series that will store the weights of the significant words and displaying this Series.<jupyter_code>ws_sent_mod_ser = pd.Series(data=ws_sent_mod_sig_words, index=un_sig_words)
ws_sent_mod_ser<jupyter_output><empty_output><jupyter_text>Learn another classifier with fewer wordsThere were a lot of words in the model we trained above. We will now train a simpler logistic regression model using only a subet of words that occur in the reviews. For this assignment, we selected a 20 words to work with. These are:<jupyter_code>significant_words = ['love', 'great', 'easy', 'old', 'little', 'perfect', 'loves', 
      'well', 'able', 'car', 'broke', 'less', 'even', 'waste', 'disappointed', 
      'work', 'product', 'money', 'would', 'return']
len(significant_words)<jupyter_output><empty_output><jupyter_text>Compute a new set of word count vectors using only these words. The CountVectorizer class has a parameter that lets you limit the choice of words when building word count vectors:<jupyter_code>vectorizer_word_subset = CountVectorizer(vocabulary=significant_words) # limit to 20 words
train_matrix_word_subset = vectorizer_word_subset.fit_transform(train_data['review_clean'])
test_matrix_word_subset = vectorizer_word_subset.transform(test_data['review_clean'])<jupyter_output><empty_output><jupyter_text>Train a logistic regression model on a subset of data We will now build a classifier with **word_count_subset** as the feature and **sentiment** as the target.  Creating an instance of the LogisticRegression class. Using the fit method to train the classifier. This model should use the sparse word count matrix (train_matrix) as features and the column sentiment of train_data as the target. Use the default values for other parameters. Call this model simple_model.<jupyter_code>log_reg = linear_model.LogisticRegression()
simple_model = logreg.fit(train_matrix_word_subset, train_data["sentiment"])<jupyter_output><empty_output><jupyter_text>Getting the weights for the 20 significant words from the simple_model<jupyter_code>ws_simp_model = list(simple_model.coef_.flatten())<jupyter_output><empty_output><jupyter_text>Putting the weights in a Series with the words corresponding to the weights as the index.<jupyter_code>ws_simp_mod_ser = pd.Series(data=ws_simp_model, index=significant_words)
ws_simp_mod_ser<jupyter_output><empty_output><jupyter_text>**Quiz Question**: Consider the coefficients of **simple_model**. How many of the 20 coefficients (corresponding to the 20 **significant_words** and *excluding the intercept term*) are positive for the `simple_model`?<jupyter_code>print len(simple_model.coef_[simple_model.coef_>0])<jupyter_output>10<jupyter_text>**Quiz Question**: Are the positive words in the **simple_model** (let us call them `positive_significant_words`) also positive words in the **sentiment_model**? ** Yes, see weights below for the significant words for the sentiment model **<jupyter_code>ws_sent_mod_ser<jupyter_output><empty_output><jupyter_text>Comparing models We will now compare the accuracy of the **sentiment_model** and the **simple_model** using the `get_classification_accuracy` method you implemented above.First, compute the classification accuracy of the **sentiment_model** on the **train_data**:<jupyter_code>acc_sent_mod_train<jupyter_output><empty_output><jupyter_text>Now, compute the classification accuracy of the **simple_model** on the **train_data**:<jupyter_code>preds_simp_mod_train = simple_model.predict(train_matrix_word_subset)
n_cor_preds_simp_mod_train = float(np.sum(preds_simp_mod_train == train_data['sentiment'].values))
n_tol_preds_simp_mod_train = float(len(preds_simp_mod_train))
acc_simp_mod_train = n_cor_preds_simp_mod_train/n_tol_preds_simp_mod_train
print acc_simp_mod_train<jupyter_output>0.866822570007<jupyter_text>**Quiz Question**: Which model (**sentiment_model** or **simple_model**) has higher accuracy on the TRAINING set?<jupyter_code>if acc_sent_mod_train>acc_simp_mod_train:
    print "sentiment_model"
else:
    print "simple_model"<jupyter_output>sentiment_model<jupyter_text>Now, we will repeat this excercise on the **test_data**. Start by computing the classification accuracy of the **sentiment_model** on the **test_data**:<jupyter_code>acc_sent_mod_test<jupyter_output><empty_output><jupyter_text>Next, we will compute the classification accuracy of the **simple_model** on the **test_data**:<jupyter_code>preds_simp_mod_test = simple_model.predict(test_matrix_word_subset)
n_cor_preds_simp_mod_test = float(np.sum(preds_simp_mod_test == test_data['sentiment'].values))
n_tol_preds_simp_mod_test = float(len(preds_simp_mod_test))
acc_simp_mod_test = n_cor_preds_simp_mod_test/n_tol_preds_simp_mod_test
print acc_simp_mod_test<jupyter_output>0.869360451164<jupyter_text>**Quiz Question**: Which model (**sentiment_model** or **simple_model**) has higher accuracy on the TEST set?<jupyter_code>if acc_sent_mod_test>acc_simp_mod_test:
    print "sentiment_model"
else:
    print "simple_model"<jupyter_output>sentiment_model<jupyter_text>Baseline: Majority class predictionIt is quite common to use the **majority class classifier** as the a baseline (or reference) model for comparison with your classifier model. The majority classifier model predicts the majority class for all data points. At the very least, you should healthily beat the majority class classifier, otherwise, the model is (usually) pointless.What is the majority class in the **train_data**?<jupyter_code>num_positive  = (train_data['sentiment'] == +1).sum()
num_negative = (train_data['sentiment'] == -1).sum()
acc_pos_train = float(num_positive)/float(len(train_data['sentiment']))
acc_neg_train = float(num_negative)/float(len(train_data['sentiment']))
if acc_pos_train>acc_neg_train:
    print "Positive Sentiment is Majority Classifier for Training Data"
else:
    print "Negative Sentiment is Majority Classifier for Training Data"<jupyter_output>Positive Sentiment is Majority Classifier for Training Data<jupyter_text>Now compute the accuracy of the majority class classifier on **test_data**.**Quiz Question**: Enter the accuracy of the majority class classifier model on the **test_data**. Round your answer to two decimal places (e.g. 0.76).<jupyter_code>num_pos_test = (test_data['sentiment'] == +1).sum()
acc_pos_test = float(num_pos_test)/float(len(test_data['sentiment']))
print "Accuracy of Majority Class Classifier on Test Data: %.2f" %(acc_pos_test)<jupyter_output>Accuracy of Majority Class Classifier on Test Data: 0.84<jupyter_text>**Quiz Question**: Is the **sentiment_model** definitely better than the majority class classifier (the baseline)?<jupyter_code>if acc_sent_mod_test>acc_pos_test:
    print "Yes, the sentiment_model is better than majority class classifier"
else:
    print "No, the majority class classifier is better than sentiment_model"<jupyter_output>Yes, the sentiment_model is better than majority class classifier
{'fraction_non_alphanumeric': 0.08790184811306104, 'fraction_numerical': 0.013006678055598695, 'mean_word_length': 6.6657738095238095, 'pattern_counts': {'":': 0, '<': 222, '<?xml version=': 0, '>': 232, 'https://': 2, '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': '60', 'dir': 'jupyter-structured-clean-dedup', 'id': '139737', 'license': 'MIT', 'n_tokens_mistral': 7989, 'n_tokens_neox': 7580, 'n_words': 2599, 'path': 'Week_1_Predicting_Sentiment_from_Reviews/week_1_lin_classifier_assign.ipynb', 'repo_name': 'Santana9937/Classification_ML_Specialization', 'size': '25756'}