<jupyter_start><jupyter_text>mnist.head()<jupyter_code>mnist.type() # not clear what the mnist dataset type is?
# the data has 70,000 images with 784 features each because each image is 28 x 28 pixel intensities
# datasets downloaded by sklearn have a dictionary structure:
# DESCR key describing the dataset
# a data key one row per instance and one column per feature
# a target key is an array with labels
X, y = mnist["data"], mnist["target"]
X.shape # gives the dimensions
y.shape # gives the dimensions
import matplotlib as mpl
import matplotlib.pyplot as plt
some_digit = X[0]
X[0]
some_digit_image = some_digit.reshape(28,28)
plt.imshow(some_digit_image, cmap="binary")
plt.imshow(some_digit_image, cmap="jet")
# now what is the label of this image?
y[0]
import numpy as np
y = y.astype(np.int8) # convert the type from string to numeric
# the dataset is already split into a training set (the first 60,000 images)
# and a test set (the last 10,000 images)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
# this data is already shuffled...might not always want to shuffle data if it's a time-series
# Training a Binary Classifier
# Start with detecting 5's
y_train_5 = (y_train == 5) # TRUE for all 5s else FALSE
y_test_5 = (y_test == 5)
# The classifier that will be used is Stochastic Gradient Descent SGD
# it handles large datasets very efficiently
# this makes it suitable for online learning
from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(random_state = 42) # setting the random state parameter helps to get the same results
sgd_clf.fit(X_train, y_train_5)
# check it on our single instance
sgd_clf.predict([some_digit])
# Evaluate Model Performance Measures
# use the cross_val_score() function to make it happen
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring = "accuracy") # the split is 3-folds
# it does greater than 90% accuracy (ratio of correct to total predictions)
# however, only 1 out of 10 images is a 5 so simply guessing "not five" will be right about 90% of the time
# so we can't use accuracy on highly skewed datasets
# instead look at the confusion matrix
from sklearn.model_selection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv = 3)
y_train_pred
from sklearn.metrics import confusion_matrix
confusion_matrix(y_train_5, y_train_pred) # evaluate the training performance
# the first column is actual class and the 2nd is predicted class
# the first row is negative class (not 5) and second is positive class (5)
# precision/accuracy TP / (TP + FP)
# recall/sensitivity TP / (TP + FN) # ratio of positive instances correctly classified
from sklearn.metrics import precision_score, recall_score
precision_score(y_train_5, y_train_pred)
recall_score(y_train_5, y_train_pred)
# F1 score is the harmonic mean of precision and recall
# it gives more weight to lower scores
from sklearn.metrics import f1_score
f1_score(y_train_5, y_train_pred)
# in some contexts you care about precision and some recall<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06950672645739911, 'fraction_numerical': 0.02626521460602178, 'mean_word_length': 5.412731006160164, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '657048', 'license': 'Unlicense', 'n_tokens_mistral': 1036, 'n_tokens_neox': 955, 'n_words': 405, 'path': 'Ch3_Classification.ipynb', 'repo_name': 'alexrootcode/homl', 'size': '3122'}