Project 19 Breast Cancer Classification using Machine Learning
Feature scaling ඉඳන් evaluation metrics දක්වා ඔක්කොම එකට එකතු කරන, high-stakes classification project එකක් — recall එක හරියට ගැනීම ඇත්තටම වැදගත් වෙන්න පුළුවන් model එකක් වර්ගයක්.
A final, high-stakes classification project pulling together everything from feature scaling to evaluation metrics — the kind of model where getting recall right can genuinely matter.
Lesson 52 of 64 · Part 4 · Evaluating & Choosing Models · Hands-on Projects · bilingual notes (English + සිංහල)
Why this matters. A final, high-stakes classification project pulling together everything from feature scaling to evaluation metrics — the kind of model where getting recall right can genuinely matter.
සිංහලෙන්: Feature scaling ඉඳන් evaluation metrics දක්වා ඔක්කොම එකට එකතු කරන, high-stakes classification project එකක් — recall එක හරියට ගැනීම ඇත්තටම වැදගත් වෙන්න පුළුවන් model එකක් වර්ගයක්.
What you'll use this for. This mirrors real diagnostic-support tools used alongside (never instead of) a doctor's judgment — the model flags likely cases for closer review.
සිංහලෙන්: Doctor කෙනෙකුගෙ තීරණයට වෙනුවට නෙවෙයි, ඒක එක්කම පාවිච්චි කරන සැබෑ diagnostic-support tools වගේම දෙයක් තමයි මේක — probable cases, ළං review එකකට flag කරනවා model එකෙන්.
Key principles
- Feature scaling matters even more when features are on wildly different scales (like cell measurements in this dataset). A feature measured in the hundreds shouldn't automatically dominate one measured in decimals — standardization (from Part 1) is what keeps the comparison fair.
Features දැඩි ලෙස වෙනස් scales වල තියෙනකොට (මේ dataset එකේ cell measurements වගේ), feature scaling එකට තව වැදගත්කම එනවා
Walkthrough
Importing the Dependencies
import numpy as np
import pandas as pd
import sklearn.datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_scoreData Collection & Processing
# loading the data from sklearn
breast_cancer_dataset = sklearn.datasets.load_breast_cancer()print(breast_cancer_dataset)Output
{'data': array([[1.799e+01, 1.038e+01, 1.228e+02, ..., 2.654e-01, 4.601e-01,
1.189e-01],
[2.057e+01, 1.777e+01, 1.329e+02, ..., 1.860e-01, 2.750e-01,
8.902e-02],
[1.969e+01, 2.125e+01, 1.300e+02, ..., 2.430e-01, 3.613e-01,
8.758e-02],
...,
[1.660e+01, 2.808e+01, 1.083e+02, ..., 1.418e-01, 2.218e-01,
7.820e-02],
[2.060e+01, 2.933e+01, 1.401e+02, ..., 2.650e-01, 4.087e-01,
1.240e-01],
[7.760e+00, 2.454e+01, 4.792e+01, ..., 0.000e+00, 2.871e-01,
7.039e-02]]), 'target': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0,
1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0,
1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1,
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0,
… (29 more lines)# loading the data to a data frame
data_frame = pd.DataFrame(breast_cancer_dataset.data, columns = breast_cancer_dataset.feature_names)# print the first 5 rows of the dataframe
data_frame.head()| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | … | |
|---|---|---|---|---|---|---|---|---|
| 0 | 17.99 | 10.38 | 122.80 | 1001.0 | 0.11840 | 0.27760 | 0.3001 | … |
| 1 | 20.57 | 17.77 | 132.90 | 1326.0 | 0.08474 | 0.07864 | 0.0869 | … |
| 2 | 19.69 | 21.25 | 130.00 | 1203.0 | 0.10960 | 0.15990 | 0.1974 | … |
| 3 | 11.42 | 20.38 | 77.58 | 386.1 | 0.14250 | 0.28390 | 0.2414 | … |
| 4 | 20.29 | 14.34 | 135.10 | 1297.0 | 0.10030 | 0.13280 | 0.1980 | … |
# adding the 'target' column to the data frame
data_frame['label'] = breast_cancer_dataset.target# print last 5 rows of the dataframe
data_frame.tail()| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | … | |
|---|---|---|---|---|---|---|---|---|
| 564 | 21.56 | 22.39 | 142.00 | 1479.0 | 0.11100 | 0.11590 | 0.24390 | … |
| 565 | 20.13 | 28.25 | 131.20 | 1261.0 | 0.09780 | 0.10340 | 0.14400 | … |
| 566 | 16.60 | 28.08 | 108.30 | 858.1 | 0.08455 | 0.10230 | 0.09251 | … |
| 567 | 20.60 | 29.33 | 140.10 | 1265.0 | 0.11780 | 0.27700 | 0.35140 | … |
| 568 | 7.76 | 24.54 | 47.92 | 181.0 | 0.05263 | 0.04362 | 0.00000 | … |
# number of rows and columns in the dataset
data_frame.shapeOutput
(569, 31)# getting some information about the data
data_frame.info()Output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 569 entries, 0 to 568
Data columns (total 31 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 mean radius 569 non-null float64
1 mean texture 569 non-null float64
2 mean perimeter 569 non-null float64
3 mean area 569 non-null float64
4 mean smoothness 569 non-null float64
5 mean compactness 569 non-null float64
6 mean concavity 569 non-null float64
7 mean concave points 569 non-null float64
8 mean symmetry 569 non-null float64
9 mean fractal dimension 569 non-null float64
10 radius error 569 non-null float64
11 texture error 569 non-null float64
12 perimeter error 569 non-null float64
… (20 more lines)# checking for missing values
data_frame.isnull().sum()Output
mean radius 0
mean texture 0
mean perimeter 0
mean area 0
mean smoothness 0
mean compactness 0
mean concavity 0
mean concave points 0
mean symmetry 0
mean fractal dimension 0
radius error 0
texture error 0
perimeter error 0
area error 0
smoothness error 0
compactness error 0
concavity error 0
concave points error 0
… (14 more lines)# statistical measures about the data
data_frame.describe()| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | … | |
|---|---|---|---|---|---|---|---|---|
| count | 569.000000 | 569.000000 | 569.000000 | 569.000000 | 569.000000 | 569.000000 | 569.000000 | … |
| mean | 14.127292 | 19.289649 | 91.969033 | 654.889104 | 0.096360 | 0.104341 | 0.088799 | … |
| std | 3.524049 | 4.301036 | 24.298981 | 351.914129 | 0.014064 | 0.052813 | 0.079720 | … |
| min | 6.981000 | 9.710000 | 43.790000 | 143.500000 | 0.052630 | 0.019380 | 0.000000 | … |
| 25% | 11.700000 | 16.170000 | 75.170000 | 420.300000 | 0.086370 | 0.064920 | 0.029560 | … |
| 50% | 13.370000 | 18.840000 | 86.240000 | 551.100000 | 0.095870 | 0.092630 | 0.061540 | … |
… 2 more rows
# checking the distribution of Target Varibale
data_frame['label'].value_counts()Output
1 357
0 212
Name: label, dtype: int641 --> Benign
0 --> Malignant
data_frame.groupby('label').mean()| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | … | |
|---|---|---|---|---|---|---|---|---|
| label | … | |||||||
| 0 | 17.462830 | 21.604906 | 115.365377 | 978.376415 | 0.102898 | 0.145188 | 0.160775 | … |
| 1 | 12.146524 | 17.914762 | 78.075406 | 462.790196 | 0.092478 | 0.080085 | 0.046058 | … |
Separating the features and target
X = data_frame.drop(columns='label', axis=1)
Y = data_frame['label']print(X)Output
mean radius mean texture ... worst symmetry worst fractal dimension
0 17.99 10.38 ... 0.4601 0.11890
1 20.57 17.77 ... 0.2750 0.08902
2 19.69 21.25 ... 0.3613 0.08758
3 11.42 20.38 ... 0.6638 0.17300
4 20.29 14.34 ... 0.2364 0.07678
.. ... ... ... ... ...
564 21.56 22.39 ... 0.2060 0.07115
565 20.13 28.25 ... 0.2572 0.06637
566 16.60 28.08 ... 0.2218 0.07820
567 20.60 29.33 ... 0.4087 0.12400
568 7.76 24.54 ... 0.2871 0.07039
[569 rows x 30 columns]print(Y)Output
0 0
1 0
2 0
3 0
4 0
..
564 0
565 0
566 0
567 0
568 1
Name: label, Length: 569, dtype: int64Splitting the data into training data & Testing data
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=2)print(X.shape, X_train.shape, X_test.shape)Output
(569, 30) (455, 30) (114, 30)Model Training
Logistic Regression
model = LogisticRegression()# training the Logistic Regression model using Training data
model.fit(X_train, Y_train)Output
/usr/local/lib/python3.7/dist-packages/sklearn/linear_model/_logistic.py:818: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG,Output
LogisticRegression()Model Evaluation
Accuracy Score
# accuracy on training data
X_train_prediction = model.predict(X_train)
training_data_accuracy = accuracy_score(Y_train, X_train_prediction)print('Accuracy on training data = ', training_data_accuracy)Output
Accuracy on training data = 0.9494505494505494# accuracy on test data
X_test_prediction = model.predict(X_test)
test_data_accuracy = accuracy_score(Y_test, X_test_prediction)print('Accuracy on test data = ', test_data_accuracy)Output
Accuracy on test data = 0.9298245614035088Building a Predictive System
input_data = (13.54,14.36,87.46,566.3,0.09779,0.08129,0.06664,0.04781,0.1885,0.05766,0.2699,0.7886,2.058,23.56,0.008462,0.0146,0.02387,0.01315,0.0198,0.0023,15.11,19.26,99.7,711.2,0.144,0.1773,0.239,0.1288,0.2977,0.07259)
# change the input data to a numpy array
input_data_as_numpy_array = np.asarray(input_data)
# reshape the numpy array as we are predicting for one datapoint
input_data_reshaped = input_data_as_numpy_array.reshape(1,-1)
prediction = model.predict(input_data_reshaped)
print(prediction)
if (prediction[0] == 0):
print('The Breast cancer is Malignant')
else:
print('The Breast Cancer is Benign')Output
[1]
The Breast Cancer is BenignOutput
/usr/local/lib/python3.7/dist-packages/sklearn/base.py:446: UserWarning: X does not have valid feature names, but LogisticRegression was fitted with feature nam
"X does not have valid feature names, but"Keep going: ← Lesson 51 · Lesson 53 → · Track it in the Self Guide
Finished this one?
Part of Self Guide · Stage 16: ML 4 — Evaluating & Choosing Models. Progress is saved in this browser.



