Compare commits

...

12 Commits

Author SHA1 Message Date
93d8bf4a5b finished TextBlob hw 2026-04-01 11:41:21 -04:00
4887c03420 added test.json 2026-04-01 11:39:35 -04:00
5d4ec549c0 added train.json 2026-04-01 11:39:20 -04:00
b12bfa4287 finished lab 2026-04-01 11:33:35 -04:00
d06c904f4b in class lab template added 2026-04-01 10:37:07 -04:00
31874b3159 phrase.txt modified 2026-04-01 10:33:16 -04:00
2f5ba2c829 initial phrases.txt 2026-04-01 10:32:53 -04:00
e4aae5bb86 added phrase.txt.bak 2026-04-01 10:32:21 -04:00
6b8a100ad0 fixed 2026-03-31 15:17:05 -04:00
9996d673f4 HW4B 2026-03-31 15:03:32 -04:00
e512774f97 added exported pdf 2026-03-29 22:07:15 -04:00
32ae8d1d46 exported as a .py 2026-03-29 22:05:09 -04:00
12 changed files with 1763 additions and 1 deletions

View File

@@ -0,0 +1,594 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "dffa60e8",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"id": "3340eabf",
"metadata": {
"cell_marker": "\"\"\""
},
"source": [
"Inclass-Lab\n",
"\n",
"Automatically generated by Colab.\n",
"\n",
"Original file is located at\n",
" https://colab.research.google.com/drive/13N7lQHvv4_LxKgcerumJ-18e5GfdBggm"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34271feb",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "9491847c",
"metadata": {
"cell_marker": "\"\"\""
},
"source": [
"In-Class Lab: Comparing Classification Models (Breast Cancer Dataset)\n",
"\n",
"Learning Objectives\n",
"\n",
"---\n",
"\n",
"\n",
"By the end of this lab, you should be able to:\n",
"\n",
"\n",
"\n",
"* Train multiple models (KNN, Logistic Regression, Decision Tree)\n",
"* Compare performance across various scenarios\n",
"* Understand the effect of scaling and evaluation methods\n",
"* Interpret confusion matrix & classification report\n",
"\n",
"\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "cceb43dc",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 1:"
]
},
{
"cell_type": "markdown",
"id": "818bfdad",
"metadata": {
"cell_marker": "'''",
"lines_to_next_cell": 0
},
"source": [
"Load dataset\n",
"Explain features/target\n",
"Do train_test_split"
]
},
{
"cell_type": "markdown",
"id": "6de94b5d",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "a8899ca0",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.datasets import load_breast_cancer\n",
"data = load_breast_cancer()\n",
"X = data.data\n",
"y = data.target\n",
"\n",
"print(data.target_names)\n",
"print(X.shape)\n",
"#0 - malignant\n",
"#1 - benigh"
]
},
{
"cell_type": "markdown",
"id": "ae1b0d61",
"metadata": {
"cell_marker": "###############################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 2: IMPORT LIBRARIES FOR CLASSIFIERS\n",
"##############################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8db6dfd6",
"metadata": {
"lines_to_next_cell": 0
},
"outputs": [],
"source": [
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.tree import DecisionTreeClassifier\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "a2301b40",
"metadata": {
"cell_marker": "#########################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 3: IMPORT MODUL FOR DATA SPLIT\n",
"########################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75fe2532",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split"
]
},
{
"cell_type": "markdown",
"id": "fb69921d",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 4: SPLIT THE DATASET\n",
"###################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6eb66fc0",
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)"
]
},
{
"cell_type": "markdown",
"id": "b182e930",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 5\n",
"TASK 1: Train 3 models (no scaling)\n",
"###################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f31f0262",
"metadata": {},
"outputs": [],
"source": [
"knn = KNeighborsClassifier(n_neighbors=5)\n",
"logreg = LogisticRegression(max_iter=5000)\n",
"tree = DecisionTreeClassifier()\n",
"\n",
"knn.fit(X_train, y_train)\n",
"logreg.fit(X_train, y_train)\n",
"tree.fit(X_train, y_train)"
]
},
{
"cell_type": "markdown",
"id": "d3e0088e",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 6\n",
"Task 2: Evaluate accuracy"
]
},
{
"cell_type": "markdown",
"id": "3a8845a1",
"metadata": {
"cell_marker": "'''",
"lines_to_next_cell": 0
},
"source": [
"* Which model performs best?\n",
"* Are the results very different?"
]
},
{
"cell_type": "markdown",
"id": "d49b62b3",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "395d887c",
"metadata": {},
"outputs": [],
"source": [
"print(\"KNN:\", knn.score(X_test, y_test))\n",
"print(\"LogReg:\", logreg.score(X_test, y_test))\n",
"print(\"Tree:\", tree.score(X_test, y_test))"
]
},
{
"cell_type": "markdown",
"id": "9de74c34",
"metadata": {
"cell_marker": "####################################"
},
"source": [
"BLOCK 7\n",
"Part 2: Evaluation Metrics\n",
"Task 3: Confusion Matrix"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "deec64c6",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import confusion_matrix\n",
"print(confusion_matrix(y_test, knn.predict(X_test)))"
]
},
{
"cell_type": "markdown",
"id": "18bc0c0e",
"metadata": {
"cell_marker": "#####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 8: CLASSIFICATION FREPORT"
]
},
{
"cell_type": "markdown",
"id": "a2e8747f",
"metadata": {
"cell_marker": "'''",
"lines_to_next_cell": 0
},
"source": [
"* Which model has better recall?\n",
"* Which is better for detecting cancer?"
]
},
{
"cell_type": "markdown",
"id": "88303af7",
"metadata": {
"cell_marker": "#####################################",
"lines_to_next_cell": 0
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "e9ef7bea",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import classification_report\n",
"print(classification_report(y_test, knn.predict(X_test)))"
]
},
{
"cell_type": "markdown",
"id": "c1d8978a",
"metadata": {
"cell_marker": "########################################"
},
"source": [
"BLOCK 9:\n",
"Part 3: Scaling Effect\n",
"Task 5: Apply scaling using pipeline\n",
"#######################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "84e1f5d4",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.pipeline import Pipeline\n",
"from sklearn.preprocessing import StandardScaler\n",
"from sklearn.metrics import accuracy_score, confusion_matrix, classification_report\n",
"\n",
"knn_scaled = Pipeline([\n",
" ('scaler', StandardScaler()),\n",
" ('knn', KNeighborsClassifier(n_neighbors=5))\n",
"])\n",
"\n",
"logreg_scaled = Pipeline([\n",
" ('scaler', StandardScaler()),\n",
" ('logreg', LogisticRegression(max_iter=5000))\n",
"])\n",
"\n",
"tree_scaled = Pipeline([\n",
" ('scaler', StandardScaler()),\n",
" ('tree', DecisionTreeClassifier(random_state=42))\n",
"])\n",
"\n",
"knn_scaled.fit(X_train, y_train)\n",
"logreg_scaled.fit(X_train, y_train)\n",
"tree_scaled.fit(X_train, y_train)\n",
"\n",
"knn_pred_scaled = knn_scaled.predict(X_test)\n",
"logreg_pred_scaled = logreg_scaled.predict(X_test)\n",
"tree_pred_scaled = tree_scaled.predict(X_test)\n",
"\n",
"print(\"\\n=== RESULTS WITH SCALING ===\")\n",
"print(\"KNN Accuracy:\", accuracy_score(y_test, knn_pred_scaled))\n",
"print(\"Logistic Regression Accuracy:\", accuracy_score(y_test, logreg_pred_scaled))\n",
"print(\"Decision Tree Accuracy:\", accuracy_score(y_test, tree_pred_scaled))"
]
},
{
"cell_type": "markdown",
"id": "d5caa8ec",
"metadata": {
"cell_marker": "#####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 10: CLASSIFICATION REPORT\n",
"####################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6643f0af",
"metadata": {},
"outputs": [],
"source": [
"print(\"\\n=== CLASSIFICATION REPORTS (WITH SCALING) ===\")\n",
"\n",
"print(\"\\nKNN Report:\")\n",
"print(classification_report(y_test, knn_pred_scaled))\n",
"\n",
"print(\"\\nLogistic Regression Report:\")\n",
"print(classification_report(y_test, logreg_pred_scaled))\n",
"\n",
"print(\"\\nDecision Tree Report:\")\n",
"print(classification_report(y_test, tree_pred_scaled))"
]
},
{
"cell_type": "markdown",
"id": "c38c51d0",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 11: CONFUSION MATRIX\n",
"###################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "444fbb13",
"metadata": {},
"outputs": [],
"source": [
"print(\"\\n=== CONFUSION MATRICES (WITH SCALING) ===\")\n",
"\n",
"print(\"\\nKNN Confusion Matrix:\")\n",
"print(confusion_matrix(y_test, knn_pred_scaled))\n",
"\n",
"print(\"\\nLogistic Regression Confusion Matrix:\")\n",
"print(confusion_matrix(y_test, logreg_pred_scaled))\n",
"\n",
"print(\"\\nDecision Tree Confusion Matrix:\")\n",
"print(confusion_matrix(y_test, tree_pred_scaled))\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "c5d82a08",
"metadata": {
"cell_marker": "###############################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 12: MODWLS WITH CROSS-VALIDATION\n",
"##############################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "17493cc3",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import cross_val_score\n",
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"knn_pipeline = Pipeline([\n",
" ('scaler', StandardScaler()),\n",
" ('knn', KNeighborsClassifier(n_neighbors=5))\n",
"])\n",
"\n",
"logreg_pipeline = Pipeline([\n",
" ('scaler', StandardScaler()),\n",
" ('logreg', LogisticRegression(max_iter=5000))\n",
"])\n",
"\n",
"tree_model = DecisionTreeClassifier(random_state=42)\n",
"\n",
"knn_cv_scores = cross_val_score(knn_pipeline, X, y, cv=5, scoring='accuracy')\n",
"logreg_cv_scores = cross_val_score(logreg_pipeline, X, y, cv=5, scoring='accuracy')\n",
"tree_cv_scores = cross_val_score(tree_model, X, y, cv=5, scoring='accuracy')\n",
"\n",
"print(\"=== Cross-Validation Results ===\")\n",
"\n",
"print(\"\\nKNN\")\n",
"print(\"CV Scores:\", knn_cv_scores)\n",
"print(\"Mean Accuracy:\", np.mean(knn_cv_scores))\n",
"print(\"Standard Deviation:\", np.std(knn_cv_scores))\n",
"\n",
"print(\"\\nLogistic Regression\")\n",
"print(\"CV Scores:\", logreg_cv_scores)\n",
"print(\"Mean Accuracy:\", np.mean(logreg_cv_scores))\n",
"print(\"Standard Deviation:\", np.std(logreg_cv_scores))\n",
"\n",
"print(\"\\nDecision Tree\")\n",
"print(\"CV Scores:\", tree_cv_scores)\n",
"print(\"Mean Accuracy:\", np.mean(tree_cv_scores))\n",
"print(\"Standard Deviation:\", np.std(tree_cv_scores))"
]
},
{
"cell_type": "markdown",
"id": "94d94dd2",
"metadata": {
"cell_marker": "####################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 13: CONFUSION MATRIX\n",
"###################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c706abc3",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import cross_val_predict\n",
"from sklearn.metrics import confusion_matrix, classification_report\n",
"\n",
"knn_pred = cross_val_predict(knn_pipeline, X, y, cv=5)\n",
"logreg_pred = cross_val_predict(logreg_pipeline, X, y, cv=5)\n",
"tree_pred = cross_val_predict(tree_model, X, y, cv=5)\n",
"\n",
"print(\"\\n=== Confusion Matrices ===\")\n",
"print(\"\\nKNN\")\n",
"print(confusion_matrix(y, knn_pred))\n",
"\n",
"print(\"\\nLogistic Regression\")\n",
"print(confusion_matrix(y, logreg_pred))\n",
"\n",
"print(\"\\nDecision Tree\")\n",
"print(confusion_matrix(y, tree_pred))\n",
"\n",
"print(\"\\n=== Classification Reports ===\")\n",
"print(\"\\nKNN\")\n",
"print(classification_report(y, knn_pred))\n",
"\n",
"print(\"\\nLogistic Regression\")\n",
"print(classification_report(y, logreg_pred))\n",
"\n",
"print(\"\\nDecision Tree\")\n",
"print(classification_report(y, tree_pred))"
]
},
{
"cell_type": "markdown",
"id": "34354ec9",
"metadata": {
"cell_marker": "###########################################",
"lines_to_next_cell": 0
},
"source": [
"BLOCK 14: LETS GET THE BEST VALUE FOR K\n",
"task: use the k value to recompute the previous KNN model and evaluate the performance\n",
"#########################################"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "93fa45e5",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import cross_val_score\n",
"import numpy as np\n",
"\n",
"k_values = range(1, 21)\n",
"scores = []\n",
"\n",
"for k in k_values:\n",
" knn = KNeighborsClassifier(n_neighbors=k)\n",
" cv_scores = cross_val_score(knn, X, y, cv=5)\n",
" scores.append(np.mean(cv_scores))\n",
"\n",
"best_k = k_values[np.argmax(scores)]\n",
"\n",
"print(\"Best k:\", best_k)\n",
"print(\"Best CV Accuracy:\", max(scores))\n"
]
}
],
"metadata": {
"jupytext": {
"cell_metadata_filter": "-all",
"encoding": "# -*- coding: utf-8 -*-",
"main_language": "python",
"notebook_metadata_filter": "-all"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,284 @@
# -*- coding: utf-8 -*-
"""Inclass-Lab
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/13N7lQHvv4_LxKgcerumJ-18e5GfdBggm
"""
"""In-Class Lab: Comparing Classification Models (Breast Cancer Dataset)
Learning Objectives
---
By the end of this lab, you should be able to:
* Train multiple models (KNN, Logistic Regression, Decision Tree)
* Compare performance across various scenarios
* Understand the effect of scaling and evaluation methods
* Interpret confusion matrix & classification report
"""
####################################
# BLOCK 1:
'''
Load dataset
Explain features/target
Do train_test_split
'''
####################################
from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
X = data.data
y = data.target
print(data.target_names)
print(X.shape)
#0 - malignant
#1 - benigh
'''
Answer: The dataset contains 569 samples with 30 features each. The target variable has two classes: 0 (malignant) and 1 (benign). The goal is to classify tumors as either malignant or benign based on the features provided.
'''
###############################
# BLOCK 2: IMPORT LIBRARIES FOR CLASSIFIERS
###############################
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
import numpy as np
#########################################
# BLOCK 3: IMPORT MODUL FOR DATA SPLIT
#########################################
from sklearn.model_selection import train_test_split
####################################
# BLOCK 4: SPLIT THE DATASET
####################################
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
####################################
# BLOCK 5
#TASK 1: Train 3 models (no scaling)
####################################
knn = KNeighborsClassifier(n_neighbors=5)
logreg = LogisticRegression(max_iter=5000)
tree = DecisionTreeClassifier()
knn.fit(X_train, y_train)
logreg.fit(X_train, y_train)
tree.fit(X_train, y_train)
####################################
# BLOCK 6
# Task 2: Evaluate accuracy
'''
* Which model performs best?
* Are the results very different?
'''
####################################
print("KNN:", knn.score(X_test, y_test))
print("LogReg:", logreg.score(X_test, y_test))
print("Tree:", tree.score(X_test, y_test))
'''
Answer: The results are as follows:
KNN: 0.956140350877193
LogReg: 0.956140350877193
Tree: 0.9298245614035088
They are all very similar, however LogReg and KNN perform slightly better than the Decision Tree in terms of accuracy on the test set. The difference is not very large, but it suggests that KNN and Logistic Regression may be more effective for this particular dataset.
'''
####################################
#BLOCK 7
# Part 2: Evaluation Metrics
# Task 3: Confusion Matrix
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, knn.predict(X_test)))
#####################################
# BLOCK 8: CLASSIFICATION FREPORT
'''
* Which model has better recall?
* Which is better for detecting cancer?
'''
'''
Answer: The recall for the model in Block 8 is 0.88 for malignant, so it correctly identifies 88% of cancer cases.
'''
#####################################
from sklearn.metrics import classification_report
print(classification_report(y_test, knn.predict(X_test)))
########################################
# BLOCK 9:
# Part 3: Scaling Effect
# Task 5: Apply scaling using pipeline
########################################
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
knn_scaled = Pipeline([
('scaler', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=5))
])
logreg_scaled = Pipeline([
('scaler', StandardScaler()),
('logreg', LogisticRegression(max_iter=5000))
])
tree_scaled = Pipeline([
('scaler', StandardScaler()),
('tree', DecisionTreeClassifier(random_state=42))
])
knn_scaled.fit(X_train, y_train)
logreg_scaled.fit(X_train, y_train)
tree_scaled.fit(X_train, y_train)
knn_pred_scaled = knn_scaled.predict(X_test)
logreg_pred_scaled = logreg_scaled.predict(X_test)
tree_pred_scaled = tree_scaled.predict(X_test)
print("\n=== RESULTS WITH SCALING ===")
print("KNN Accuracy:", accuracy_score(y_test, knn_pred_scaled))
print("Logistic Regression Accuracy:", accuracy_score(y_test, logreg_pred_scaled))
print("Decision Tree Accuracy:", accuracy_score(y_test, tree_pred_scaled))
#####################################
# BLOCK 10: CLASSIFICATION REPORT
#####################################
print("\n=== CLASSIFICATION REPORTS (WITH SCALING) ===")
print("\nKNN Report:")
print(classification_report(y_test, knn_pred_scaled))
print("\nLogistic Regression Report:")
print(classification_report(y_test, logreg_pred_scaled))
print("\nDecision Tree Report:")
print(classification_report(y_test, tree_pred_scaled))
####################################
# BLOCK 11: CONFUSION MATRIX
####################################
print("\n=== CONFUSION MATRICES (WITH SCALING) ===")
print("\nKNN Confusion Matrix:")
print(confusion_matrix(y_test, knn_pred_scaled))
print("\nLogistic Regression Confusion Matrix:")
print(confusion_matrix(y_test, logreg_pred_scaled))
print("\nDecision Tree Confusion Matrix:")
print(confusion_matrix(y_test, tree_pred_scaled))
###############################################
# BLOCK 12: MODWLS WITH CROSS-VALIDATION
###############################################
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
knn_pipeline = Pipeline([
('scaler', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=5))
])
logreg_pipeline = Pipeline([
('scaler', StandardScaler()),
('logreg', LogisticRegression(max_iter=5000))
])
tree_model = DecisionTreeClassifier(random_state=42)
knn_cv_scores = cross_val_score(knn_pipeline, X, y, cv=5, scoring='accuracy')
logreg_cv_scores = cross_val_score(logreg_pipeline, X, y, cv=5, scoring='accuracy')
tree_cv_scores = cross_val_score(tree_model, X, y, cv=5, scoring='accuracy')
print("=== Cross-Validation Results ===")
print("\nKNN")
print("CV Scores:", knn_cv_scores)
print("Mean Accuracy:", np.mean(knn_cv_scores))
print("Standard Deviation:", np.std(knn_cv_scores))
print("\nLogistic Regression")
print("CV Scores:", logreg_cv_scores)
print("Mean Accuracy:", np.mean(logreg_cv_scores))
print("Standard Deviation:", np.std(logreg_cv_scores))
print("\nDecision Tree")
print("CV Scores:", tree_cv_scores)
print("Mean Accuracy:", np.mean(tree_cv_scores))
print("Standard Deviation:", np.std(tree_cv_scores))
####################################
# BLOCK 13: CONFUSION MATRIX
####################################
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix, classification_report
knn_pred = cross_val_predict(knn_pipeline, X, y, cv=5)
logreg_pred = cross_val_predict(logreg_pipeline, X, y, cv=5)
tree_pred = cross_val_predict(tree_model, X, y, cv=5)
print("\n=== Confusion Matrices ===")
print("\nKNN")
print(confusion_matrix(y, knn_pred))
print("\nLogistic Regression")
print(confusion_matrix(y, logreg_pred))
print("\nDecision Tree")
print(confusion_matrix(y, tree_pred))
print("\n=== Classification Reports ===")
print("\nKNN")
print(classification_report(y, knn_pred))
print("\nLogistic Regression")
print(classification_report(y, logreg_pred))
print("\nDecision Tree")
print(classification_report(y, tree_pred))
###########################################
# BLOCK 14: LETS GET THE BEST VALUE FOR K
# task: use the k value to recompute the previous KNN model and evaluate the performance
##########################################
from sklearn.model_selection import cross_val_score
import numpy as np
k_values = range(1, 21)
scores = []
for k in k_values:
knn = KNeighborsClassifier(n_neighbors=k)
cv_scores = cross_val_score(knn, X, y, cv=5)
scores.append(np.mean(cv_scores))
best_k = k_values[np.argmax(scores)]
print("Best k:", best_k)
print("Best CV Accuracy:", max(scores))

View File

@@ -0,0 +1,4 @@
When IN the course
of human events IN
the space of one
place IN time IN memory

View File

@@ -0,0 +1,4 @@
When in the course
of human events in
the space of one
place in time in memory

56
HW 4B/HW4.py Normal file
View File

@@ -0,0 +1,56 @@
import requests
import time
import json
import os
def printQuake(properties):
magnitude = properties["mag"]
location = properties["place"]
timestamp = properties["time"] / 1000
time_str = time.strftime("%H:%M:%S", time.gmtime(timestamp))
date_str = time.strftime("%a, %d %b %Y", time.gmtime(timestamp))
print(f"At {time_str} on {date_str}: earthquake of magnitude {magnitude} at {location}")
def fetchAndPrintQuakes(start_date, end_date, min_magnitude):
url = "https://earthquake.usgs.gov/fdsnws/event/1/query"
params = {
"method": "query",
"format": "geojson",
"starttime": start_date,
"endtime": end_date,
"minmagnitude": min_magnitude
}
response = requests.get(url, params=params)
data = response.json()
for quake in data["features"]:
printQuake(quake["properties"])
def readAndPrintQuakes(filename):
script_dir = os.path.dirname(__file__)
filepath = os.path.join(script_dir, filename)
with open(filepath, "r") as f:
data = json.load(f)
for quake in data["features"]:
printQuake(quake["properties"])
def main():
print("Earthquakes from API:")
fetchAndPrintQuakes("2023-10-01", "2023-10-03", 5.0)
print("\nEarthquakes from saved JSON:")
readAndPrintQuakes("load.json")
if __name__ == "__main__":
main()

7
HW 4B/load.json Normal file
View File

@@ -0,0 +1,7 @@
{"type":"FeatureCollection","metadata":{"generated":1774984347000,"url":"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&minmagnitude=5.4&starttime=2025-09-25&endtime=2025-09-30","title":"USGS Earthquakes","status":200,"api":"2.4.0","count":7},"features":[{"type":"Feature","properties":{"mag":5.5,"place":"89 km E of Petropavlovsk-Kamchatsky, Russia","time":1759183643711,"updated":1765489240040,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rdnq","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rdnq&format=geojson","felt":1,"cdi":3.8,"mmi":4.454,"alert":"green","status":"reviewed","tsunami":0,"sig":466,"net":"us","code":"6000rdnq","ids":",us6000rdnq,usauto6000rdnq,pt25272000,","sources":",us,usauto,pt,","types":",dyfi,internal-moment-tensor,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,","nst":101,"dmin":0.785,"rms":0.84,"gap":60,"magType":"mww","type":"earthquake","title":"M 5.5 - 89 km E of Petropavlovsk-Kamchatsky, Russia"},"geometry":{"type":"Point","coordinates":[159.9446,52.9637,42]},"id":"us6000rdnq"},
{"type":"Feature","properties":{"mag":5.5,"place":"south of the Fiji Islands","time":1759049581242,"updated":1765489239040,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rdex","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rdex&format=geojson","felt":null,"cdi":null,"mmi":1,"alert":"green","status":"reviewed","tsunami":0,"sig":465,"net":"us","code":"6000rdex","ids":",usauto6000rdex,us6000rdex,","sources":",usauto,us,","types":",internal-moment-tensor,losspager,moment-tensor,origin,phase-data,shakemap,","nst":58,"dmin":6.142,"rms":0.94,"gap":71,"magType":"mww","type":"earthquake","title":"M 5.5 - south of the Fiji Islands"},"geometry":{"type":"Point","coordinates":[178.8114,-23.8765,573.583]},"id":"us6000rdex"},
{"type":"Feature","properties":{"mag":5.5,"place":"90 km WNW of Sola, Vanuatu","time":1758960648598,"updated":1765489241040,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rdan","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rdan&format=geojson","felt":null,"cdi":null,"mmi":4.159,"alert":"green","status":"reviewed","tsunami":0,"sig":465,"net":"us","code":"6000rdan","ids":",usauto6000rdan,us6000rdan,","sources":",usauto,us,","types":",internal-moment-tensor,losspager,moment-tensor,origin,phase-data,shakemap,","nst":142,"dmin":7.205,"rms":0.81,"gap":50,"magType":"mww","type":"earthquake","title":"M 5.5 - 90 km WNW of Sola, Vanuatu"},"geometry":{"type":"Point","coordinates":[166.7322,-13.6974,33]},"id":"us6000rdan"},
{"type":"Feature","properties":{"mag":5.9,"place":"239 km W of Bandon, Oregon","time":1758869128067,"updated":1774594539969,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rd1w","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rd1w&format=geojson","felt":29,"cdi":2.5,"mmi":0,"alert":"green","status":"reviewed","tsunami":1,"sig":543,"net":"us","code":"6000rd1w","ids":",at00t36o3y,us6000rd1w,usauto6000rd1w,pt25269000,","sources":",at,us,usauto,pt,","types":",dyfi,event-sequence,impact-link,internal-moment-tensor,internal-origin,losspager,moment-tensor,oaf,origin,phase-data,shakemap,","nst":85,"dmin":2.395,"rms":0.81,"gap":167,"magType":"mww","type":"earthquake","title":"M 5.9 - 239 km W of Bandon, Oregon"},"geometry":{"type":"Point","coordinates":[-127.3203,43.4524,10]},"id":"us6000rd1w"},
{"type":"Feature","properties":{"mag":5.4,"place":"72 km SSW of Isangel, Vanuatu","time":1758842212037,"updated":1765489243040,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rcyv","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rcyv&format=geojson","felt":null,"cdi":null,"mmi":3.885,"alert":"green","status":"reviewed","tsunami":0,"sig":449,"net":"us","code":"6000rcyv","ids":",usauto6000rcyv,us6000rcyv,","sources":",usauto,us,","types":",internal-moment-tensor,losspager,moment-tensor,origin,phase-data,shakemap,","nst":48,"dmin":2.873,"rms":0.75,"gap":67,"magType":"mww","type":"earthquake","title":"M 5.4 - 72 km SSW of Isangel, Vanuatu"},"geometry":{"type":"Point","coordinates":[169.0959,-20.1733,49.94]},"id":"us6000rcyv"},
{"type":"Feature","properties":{"mag":5.7,"place":"183 km SSW of Emiliano Zapata, Mexico","time":1758795384902,"updated":1765489238040,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rcsb","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rcsb&format=geojson","felt":0,"cdi":1,"mmi":3.513,"alert":"green","status":"reviewed","tsunami":0,"sig":500,"net":"us","code":"6000rcsb","ids":",us6000rcsb,usauto6000rcsb,pt25268001,","sources":",us,usauto,pt,","types":",dyfi,internal-moment-tensor,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,","nst":82,"dmin":2.375,"rms":1,"gap":118,"magType":"mww","type":"earthquake","title":"M 5.7 - 183 km SSW of Emiliano Zapata, Mexico"},"geometry":{"type":"Point","coordinates":[-105.8786,17.9793,10]},"id":"us6000rcsb"},
{"type":"Feature","properties":{"mag":6.3,"place":"25 km ENE of Mene Grande, Venezuela","time":1758772299565,"updated":1765489239040,"tz":null,"url":"https://earthquake.usgs.gov/earthquakes/eventpage/us6000rcqw","detail":"https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us6000rcqw&format=geojson","felt":224,"cdi":5.2,"mmi":7.744,"alert":"yellow","status":"reviewed","tsunami":1,"sig":766,"net":"us","code":"6000rcqw","ids":",pt25268000,us6000rcqw,at00t34le6,usauto6000rcqw,","sources":",pt,us,at,usauto,","types":",dyfi,ground-failure,impact-link,impact-text,internal-moment-tensor,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,","nst":113,"dmin":1.048,"rms":0.94,"gap":27,"magType":"mww","type":"earthquake","title":"M 6.3 - 25 km ENE of Mene Grande, Venezuela"},"geometry":{"type":"Point","coordinates":[-70.7081,9.9355,14]},"id":"us6000rcqw"}],"bbox":[-127.3203,-23.8765,10,178.8114,52.9637,573.583]}

BIN
HW 5/Ben Adovasio HW 5.pdf Normal file

Binary file not shown.

764
HW 5/Final_HW5.py Normal file
View File

@@ -0,0 +1,764 @@
# %%
############################
# BLOCK 1: IMPORTS
############################
# libraries!
import numpy as np # numpy is Python's "array" library
import pandas as pd # Pandas is Python's "data" library ("dataframe" == spreadsheet)
# %%
# %%
#############################
# BLOCK 2: VARIABLES LISTING
#############################
# for reference, as you work throughout, come back and list all the variable names
# here along with what that variable holds
# Variable: Contents
# -------------------
# [FILL IN VARS BELOW]
#
# %%
####################################
#from sklearn.datasets import load_iris
#data = load_iris()
#df = pd.DataFrame(data.data, columns=data.feature_names)
#df
# %%
#############################
# BLOCK 3: READING DATA
#############################
# let's read in our flower data...
#
filename = 'iris.csv'
df = pd.read_csv(filename, header=0) # encoding="latin1" et al.
print(f"{filename}: file read into a pandas DataFrame.")
df.head()
# %%
#############################
# BLOCK 4: SETTING OPTIONS
#############################
#
# a dataframe is a "spreadsheet in Python"
# (this one seems to have an extra column!)
#
pd.set_option('display.max_rows', 8) # None for no limit; default: 10
pd.set_option('display.min_rows', 8) # None for no limit; default: 10
# let's view it!
df
# %%
##############################
# BLOCK 5: USING DF'S .info()
##############################
#
# let's look at our pandas DataFrame's info (Aargh: that extra column!)
#
df.info()
# %%
#############################
# BLOCK 6: CLEANING DATA
#############################
#
# let's drop that last column (dropping is usually by _name_):
#
# if you want a list of the column names use df.columns
#col5name = df.columns[5] # get column name at index 5
df_clean = df.drop(columns=['junk']) # drop by name is typical, but what else is possible?
df_clean.info() # Is the bad last column gone?
# %%
##############################
# BLOCK 7: FEATURE NAMES DICT
##############################
#
# let's keep our column names in variables, for reference;
# in machine learning contexts, these are referred to as "features"
#
features = df_clean.columns # "list" of columns
print(f"FEATURES: {features}\n")
# It's a "pandas" list, called an Index
# use it just as a Python list of strings:
print(f"First feature: {features[0]}\n")
# let's create a dictionary to look up any column index by name
feature_name_to_index = {}
for i, name in enumerate(features):
feature_name_to_index[name] = i # using the name (as key), assign the value (i)
print(f"feature_name_to_index: {feature_name_to_index}")
# %%
##############################
# BLOCK 8: INSPECTING DATA
##############################
#
# let's look at our cleaned-up dataframe...
#
df_clean.info()
print('=' * 70)
#
# Notice that the non-null count is _different_ for irisname!
# Why? Show a table and inspect...
print(df_clean)
print('=' * 70)
# or more to the point, grab that column and inspect:
print(f"Irisname entries: {df_clean['irisname'].unique()}")
# also note how the last two rows in the df have problems, among others...
# %%
df.columns
# %%
##############################
# BLOCK 9: USING DF'S dropna
##############################
#
# typically, after dropping columns that we don't want,
# we drop rows with missing data (other approaches are possible, too)
#
df_clean = df_clean.dropna() # this removes all rows with nan items
df_clean.info()
print('=' * 70)
df_clean
#
# notice that _all_ of the rows now have 144 non-null items
# also, the first and last rows (among others) aren't valid data...
# we'll handle that next
# %%
################################
# BLOCK 10: REMOVING BOGUS DATA
################################
# or more to the point, grab that column and inspect:
print(f"Irisname entries: {df_clean['irisname'].unique()}")
print(df_clean['irisname'] == 'alieniris') # what does this show?
print(df_clean['irisname'] != 'alieniris') # what does this show?
# define a final version of the DataFrame by pulling out the
# bad alieniris data (remember that you can pass a boolean
# Series to select data that you want)
df_final = df_clean[df_clean['irisname'] != 'alieniris'].copy()
# ^^^^ YOU NEED TO WRITE CODE HERE...
print(df_final.shape)
df_final
# %%
##########################################
# BLOCK 11: CONVERT SPECIES NAME TO INDEX
##########################################
# all of scikit-learn's ML routines need numbers, not strings
# ... even for categories/classifications (like species!)
# so, we will convert the flower-species to numbers:
species_names = df_final['irisname'].unique()
species_name_to_index = { species_names[i]:i for i in range(len(species_names))}
print(species_name_to_index)
print(type(species_name_to_index))
def convertSpecies(species_name: str) -> int:
''' return the species index (a unique integer/category) '''
#print(f"converting {species_name}...")
return species_name_to_index[species_name]
# Let's try it out...
for name in species_names:
print(f"{name} maps to {convertSpecies(name)}")
# %%
##########################################
# BLOCK 12: USING DF'S .apply
##########################################
#
# we can "apply" our new convertSpecies function to a whole column
#
# (The following will issue a "SettingWithCopyWarning" here...)
# see https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
#
# >>> ADD CODE HERE TO KEEP THE WARNING FROM HAPPENING <<<
df_final.loc[:, 'irisname'] = df_final['irisname'].apply(convertSpecies)
#df_final.loc[:, 'irisname'] = df_final['irisname'].apply(convertSpecies)
# Don't run this twice! Why?! What's "KeyError: 0"?
# (of course, you can always go back and re-establish definitions of df_final)
# %%
##########################################
# BLOCK 13: CONFIRMING FINAL DATAFRAME
##########################################
#
# let's see it! (this is safe to run many times...)
#
df_final # print(df_final.tostring()) # for _all_ rows...
# %%
##########################################
# BLOCK 14: CONVERTING TO NUMPY FORMAT
##########################################
#
# let's convert our dataframe to a numpy array, named A
# Our ML library, scikit-learn operates entirely on numpy arrays.
#
#A = df_final.values
A = df_final.to_numpy() # better -- self-documenting!
print(f"type of A: {type(A)}")
print(df_final.head())
print(f"A[0] = {A[0]}")
# %%
##################################################
# BLOCK 15: CONVERTING NUMPY ARRAY TO ALL FLOATS
##################################################
#
# let's convert to make sure it's all floating-point, so we can multiply and divide
#
A = A.astype('float64') # so many: www.tutorialspoint.com/numpy/numpy_data_types.htm
A
# %%
##########################################
# BLOCK 16: USING NUMPY'S .shape
##########################################
#
# nice to have num_rows and num_cols variables handy...
#
num_rows, num_cols = A.shape
print(f"\nThe dataset has {num_rows} rows and {num_cols} cols")
print(A)
# %%
##########################################
# BLOCK 17: PRINTING FLOWER INFO
##########################################
# let's use all of our previously-defined variables, to reinforce names...
# choose a row index (particular flower) arbitrarily:
flower = 132
print(f"flower #{flower} data is {A[flower]}")
for i in range(len(features)):
col_name = features[i]
if col_name != 'irisname':
print(f" Its {col_name} is {A[flower][i]}")
else:
species_num = int(A[flower][i])
species_name = species_names[species_num]
print(f" Its {col_name} is {species_name} ({species_num})")
# %%
##########################################
# BLOCK 18: WRITING OUR OWN 1-NN FUNCTION
##########################################
#
# We don't have to use scikit-learn to implement NN!
#
#
# data-driven predictive model (1-nearest-neighbor)
#
# Python functions are first-class objects!
dist = np.linalg.norm # built in to numpy... but what does norm do?
num_rows, num_cols = A.shape # data size
def predictiveModel( features: list[float] ) -> str:
""" input: a list of four features
[ sepallen, sepalwid, petallen, petalwid ]
output: the predicted species of iris, from
setosa (0), versicolor (1), virginica (2)
"""
our_features = np.asarray(features) # make a numpy array
closest_flower = A[0]
closest_features = A[0,0:4]
closest_distance = dist(our_features - closest_features)
for i in range(1, num_rows, 1):
current_flower = A[i]
current_features = A[i,0:4]
current_distance = dist(our_features - current_features)
if current_distance < closest_distance:
closest_distance = current_distance # remember closest!
closest_flower = current_flower
# done comparing with every flower in the dataset
predicted_species = int(round(closest_flower[4])) # what type is closest_flower?
name = species_names[predicted_species]
return f"{name} ({predicted_species})"
#
# Try it!
#
# features = eval(input("Enter new features: "))
#
features = [ 4.6, 3.6, 3.0, 1.2 ]
result = predictiveModel( features )
print(f"I predict {result} from features {features}")
# %%
##########################################
# BLOCK 19: COMMENTS ON SCIKIT-LEARN kNN
##########################################
#
# but, we don't have to write our own ... because
#
# we want knn for any k (not just k=1 as above)
# we want an already-debugged algorithm!
# we want to ask iris-related questions instead of implementation ones...
#
# %%
################################################
# BLOCK 20: DEFINIING FEATURES & LABELS FOR kNN
################################################
print("+++ Start of data definitions +++\n")
X_all = A[:,0:4] # X (features) ... is all rows, columns 0, 1, 2, 3
y_all = A[:,4] # y (labels) ... is all rows, column 4 only
# (look back at slide 20)
print(f"X_all (just features) is \n {X_all}")
print(f"y_all (just labels) is \n {y_all}")
# %%
################################################
# BLOCK 21: REWEIGHTING FEATURES
################################################
#
# we can re-weight different features here...
#
col_weights = { # could be called feature weight...
'sepallen':1.0,
'sepalwid':1.0,
'petallen':1.0,
'petalwid':1.0,
}
for col_name in col_weights:
i = feature_name_to_index[col_name] # get the column index, i, of the column name
weight = col_weights[col_name] # from the dictionary above
print(f"Weighting {col_name} by {weight}")
# weighting == "multiplying"
X_all[:,i] *= weight # multiply by the weight to give this column ("feature")
# %%
################################################
# BLOCK 22: PERMUTING THE DATA
################################################
#
#
# we scramble the data, to give a different TRAIN/TEST split each time...
#
indices = np.random.permutation(len(y_all)) # indices is a permutation-list
# we scramble both X and y, necessarily with the same permutation
X_labeled = X_all[indices] # we apply the _same_ permutation to each!
y_labeled = y_all[indices] # again...
print(X_labeled) # note that X_labeled and y_labeled are permuted identically
print(y_labeled)
# %%
################################################
# BLOCK 23: DEFINING TRAIN VS TEST SETS
################################################
#
# We next separate into test data and training data ...
# + We will train on the training data...
# + We will _not_ look at the testing data when building the model
#
# Then, afterward, we will test on the testing data -- and see how well we do!
#
#
# a common convention: train on 80%, test on 20% Let's define the TEST_PERCENT
#
num_rows = X_labeled.shape[0] # the number of labeled rows
test_percent = 0.20
test_size = int(test_percent * num_rows) # no harm in rounding down
X_test = X_labeled[:test_size] # first section are for testing
y_test = y_labeled[:test_size]
X_train = X_labeled[test_size:] # all the rest are for training
y_train = y_labeled[test_size:]
num_train_rows = len(y_train)
num_test_rows = len(y_test)
print(f"total rows: {num_rows}; training with {num_train_rows} rows; testing with {num_test_rows} rows" )
print(f"\t(sanity check: {num_train_rows} + {num_test_rows} = {num_train_rows + num_test_rows})")
# %%
#######################################################
# BLOCK 24: FIRST ATTEMPT TO BUILD & TRAIN A kNN MODEL
#######################################################
#
# +++ This is the "Model-building and Model-training Cell"
#
# Create a kNN model and train it!
#
from sklearn.neighbors import KNeighborsClassifier
k = 84 # we don't know what k to use, so we guess for now! (this will _not_ be a good value)
knn_model = KNeighborsClassifier(n_neighbors = k) # here, k is the "k" in kNN
# we train the model (it's one line!)
knn_model.fit(X_train, y_train) # yay! trained!
print("Created and trained a knn classifier with k =", k)
# %%
################################################
# BLOCK 25: TEST THE kNN MODEL
################################################
#
# +++ This is the "Model-testing Cell"
#
# Now, let's see how well we did on our "held-out data" (the testing data)
#
# We run our test set!
predicted_labels = knn_model.predict(X_test)
actual_labels = y_test
# Let's print them so we can compare...
print("Predicted labels:", predicted_labels)
print("Actual labels :", actual_labels)
# And, some overall results
num_correct = sum(predicted_labels == actual_labels)
total = len(actual_labels)
print(f"\nResults on test set: {num_correct} correct out of {total} total.")
# %%
################################################
# BLOCK 26: PRETTY-PRINT PREDICTED LABELS
################################################
#
# Let's print these more helpfully, in a vertical table
#
def compareLabels(predicted_labels: np.ndarray, actual_labels: np.ndarray) -> int:
''' a more neatly formatted comparison, returning the number correct '''
num_labels = len(predicted_labels)
num_correct = 0
for i in range(num_labels):
predicted = int(round(predicted_labels[i])) # round-to-int protects from float imprecision
actual = int(round(actual_labels[i]))
result = "incorrect"
if predicted == actual: # if they match,
result = "" # no longer incorrect
num_correct += 1 # and we count a match!
# note the justification formatting:
# :>3d right justifies integers (d) to width 3
# :<12s left justifies strings (s) to width 12
print(f"row {i:>3d} : ", end = "")
print(f"{species_names[predicted]:>12s} ", end = "")
print(f"{species_names[actual]:<12s} {result}")
print()
print(f"Correct: {num_correct} out of {num_labels}")
return num_correct
#
# let's try it out!
#
compareLabels(predicted_labels,actual_labels)
# %%
################################################
# BLOCK 27: USE THE FIRST-ATTEMPT kNN MODEL
################################################
#
# Ok! We have our knn model, we could just use it...
#
#
# data-driven predictive model (k-nearest-neighbor), using scikit-learn
#
def predictiveModel( features: list[float] ) -> str:
''' input: a list of four features
[ sepallen, sepalwid, petallen, petalwid ]
output: the predicted species of iris, from
setosa (0), versicolor (1), virginica (2)
'''
our_features = np.asarray([features]) # extra brackets needed
predicted_species = knn_model.predict(our_features)
print(f"predicted_species = {predicted_species}")
predicted_species = int(round(predicted_species[0])) # unpack one element
name = species_names[predicted_species]
return f"{name} ({predicted_species})"
#
# Try it!
#
# features = eval(input("Enter new features: "))
#
features = [6.7,3.3,5.7,2.1] # [5.8,2.7,4.1,1.0] [4.6,3.6,3.0,2.2] [6.7,3.3,5.7,2.1]
result = predictiveModel( features )
print(f"I predict {result} from features {features}")
# %%
################################################
# BLOCK 28: COMMENTS ON CHOICE OF BEST k
################################################
#
# Except, we didn't really explore whether this was the BEST model we could build!
#
#
# We used k = 84 (a neighborhood size of 84 flowers)
# In a dataset of only 140ish flowers, with three species, this seems like a bad idea!
#
# Perhaps we should try ALL the neighborhood sizes in their own TRAIN/TEST split
# and see which neighborhood size works the best, for irises, at least...
#
# %%
################################################
# BLOCK 29: USING CROSS VALIDATION
################################################
#
# to do this, we use "cross validation"
# (see slide 45)
#
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score
#
# cross-validation splits the training set into two pieces:
# + model-building and model-validation. We'll use "build" and "validate"
#
max_k = 85
all_accuracies = []
best_k = 1
best_accuracy = -1
for k in range(1, max_k, 1):
knn_cv_model = KNeighborsClassifier(n_neighbors=k)
cv_scores = cross_val_score(knn_cv_model, X_train, y_train, cv=5)
this_cv_accuracy = cv_scores.mean()
print(f"k: {k:2d} cv accuracy: {this_cv_accuracy:7.4f}")
all_accuracies.append(this_cv_accuracy)
if this_cv_accuracy > best_accuracy:
best_accuracy = this_cv_accuracy
best_k = k
# assign best value of k to best_k
#best_k = k # *** AT THE MOMENT THIS IS INCORRECT ***
# you'll need to modify the loop above to find and remember the real best_k
print(f"best_k = {best_k} yields the highest average cv accuracy.") # print the best one
plt.figure(figsize=(10, 6))
sns.lineplot(x=range(1,len(all_accuracies)+1), y=all_accuracies)
plt.xlabel("k value (index)")
plt.ylabel("Cross-validated accuracy")
plt.title("kNN Accuracy vs k Value")
plt.show()
# %%
################################################
# BLOCK 30: RE-BUILD & RE-TRAIN USING BEST k
################################################
#
# Now, we re-create and re-run the "Model-building and -training Cell"
#
# Now, using best_k instead of the original, randomly-guessed value How does it do?!
#
from sklearn.neighbors import KNeighborsClassifier
knn_model_tuned = KNeighborsClassifier(n_neighbors = best_k) # here, we use the best_k
# we train the model (one line!)
knn_model_tuned.fit(X_train, y_train) # yay! trained!
print(f"Created + trained a knn classifier, now tuned with a (best) k of {best_k}")
# %%
################################################
# BLOCK 31: RE-TEST THE BEST-k MODEL
################################################
#
# Re-create and re-run the "Model-testing Cell" How does it do with best_k?!
#
predicted_labels = knn_model_tuned.predict(X_test)
actual_labels = y_test
# Let's print them so we can compare...
print("Predicted labels:", predicted_labels)
print("Actual labels:", actual_labels)
print()
# and, we'll print our nicer table...
compareLabels(predicted_labels,actual_labels)
# %%
################################################
# BLOCK 32: TRYING DIFFERENT PERMUTATIONS
################################################
#
# Before moving on, go back and choose a new permutation to give
# new testing and training sets, and go back through the steps
# for identifying the "best" k (starting at Block 22 and re-doing
# up through Block 31).
#
# Repeat this several times.
# Do you get the same value for k each time? Why or why not?
#
# %%
####################################################
# BLOCK 33: REBUILD & TRAIN USING BEST k & ALL DATA
####################################################
# Ok! Now we have tuned knn to use the "best" value of k...
#
# And, we should really use ALL available data to train our final predictive model
# (not split into test and train as before)
#
knn_model_final = KNeighborsClassifier(n_neighbors=best_k) # here, we use the best_k
knn_model_final.fit(X_all, y_all) # yay! trained!
print(f"Created + trained a 'final' knn classifier, with a (best) k of {best_k}")
# %%
####################################################
# BLOCK 34: TRYING FINAL MODEL "IN THE WILD"
####################################################
#
# final predictive model (k-nearest-neighbor), with tuned k + ALL data incorporated
#
def predictiveModel( features: list[float] ) -> str:
''' input: a list of four features
[ sepallen, sepalwid, petallen, petalwid ]
output: the predicted species of iris, from
setosa (0), versicolor (1), virginica (2)
'''
our_features = np.asarray([features]) # extra brackets needed
predicted_species = knn_model_final.predict(our_features)
predicted_species = int(round(predicted_species[0])) # unpack one element
name = species_names[predicted_species]
return f"{name} ({predicted_species})"
#
# Try it on several!
#
# features = eval(input("Enter new features: "))
#
features = [6.7,3.3,5.7,2.1] # [5.8,2.7,4.1,1.0] [4.6,3.6,3.0,2.2] [6.7,3.3,5.7,2.1]
result = predictiveModel( features )
print(f"I predict {result} from features {features}")
# %%
################################################################
# BLOCK 35a: HOW DOES THE MODEL PERFORM ON MEAN OF EACH FLOWER?
################################################################
# let's recall the species names and their order in the list
print(species_names)
print('=' * 70)
# and let's recall what the final DataFrame looks like, noting that
# the irisname was converted to the corresponding index in species_names
print(df_final)
# %%
################################################################
# BLOCK 35b: HOW DOES THE MODEL PERFORM ON MEAN OF EACH FLOWER?
################################################################
# let's grab the data from df_final corresponding to versicolor
versicolor_data = df_final[ df_final['irisname'] == convertSpecies('versicolor') ]
print(versicolor_data)
print('=' * 70)
# let's print the mean of each column
print(versicolor_data.mean())
print('=' * 70)
# and let's grab the features means only (don't need the label) for versicolor
versicolor_features_means = np.asarray(versicolor_data.mean()[:-1])
print(versicolor_features_means)
# now run the predictive model (see Block 34 above) and print a corresponding
# message
# >>> YOU ADD CODE HERE
result = predictiveModel(versicolor_features_means)
print(f"Mean versicolor features {versicolor_features_means} -> {result}")
# %%
################################################################
# BLOCK 35c: HOW DOES THE MODEL PERFORM ON MEAN OF EACH FLOWER?
################################################################
# Automate the process used in Block 35b, across all species:
#
# Loop across species names, and for each species,
# (a) pull that corresponding data from df_final
# (b) compute the means of the features, storing as a numpy array
# (c) call the predictive model using those features
# (d) print a corresponding message
# >> YOU ADD CODE HERE -- YOU SHOULD NEED NO MORE THAN 5 LINES OF CODE
for name in species_names:
species_data = df_final[df_final['irisname'] == convertSpecies(name)]
species_features_means = np.asarray(species_data.mean()[:-1])
result = predictiveModel(species_features_means)
print(f"Mean {name} features {species_features_means} -> {result}")

View File

@@ -752,7 +752,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": null,
"metadata": { "metadata": {
"id": "h0spkxGzKPR-" "id": "h0spkxGzKPR-"
}, },

6
TextBlob/test.json Normal file
View File

@@ -0,0 +1,6 @@
[
{"text": "The beer was good.", "label": "pos"},
{"text": "I do not enjoy my job", "label": "neg"},
{"text": "I feel amazing!", "label": "pos"},
{"text": "I am very tired", "label": "neg"}
]

View File

@@ -0,0 +1,31 @@
from textblob.classifiers import NaiveBayesClassifier
from pathlib import Path
def main():
# Get directory where this script is located
base_dir = Path(__file__).parent
# Build paths to data files
train_path = base_dir / "train.json"
test_path = base_dir / "test.json"
# Load training data
with open(train_path, "r") as train_file:
classifier = NaiveBayesClassifier(train_file, format="json")
# Load test data
with open(test_path, "r") as test_file:
accuracy = classifier.accuracy(test_file)
print("Accuracy:", accuracy)
print("Classifying sentences:")
print("I love this place ->", classifier.classify("I love this place"))
print("I hate this job ->", classifier.classify("I hate this job"))
print("\nMost Informative Features:")
classifier.show_informative_features(5)
if __name__ == "__main__":
main()

12
TextBlob/train.json Normal file
View File

@@ -0,0 +1,12 @@
[
{"text": "I love this sandwich.", "label": "pos"},
{"text": "This is an amazing place!", "label": "pos"},
{"text": "I feel very good about these beers.", "label": "pos"},
{"text": "This is my best work.", "label": "pos"},
{"text": "What an awesome view", "label": "pos"},
{"text": "I do not like this restaurant", "label": "neg"},
{"text": "I am tired of this stuff.", "label": "neg"},
{"text": "I can't deal with this", "label": "neg"},
{"text": "He is my sworn enemy!", "label": "neg"},
{"text": "My boss is horrible.", "label": "neg"}
]