{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"datasetVersion","sourceId":1849228,"datasetId":1099851,"databundleVersionId":1887003}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Breast Cancer Tumour Diagnosis Prediction using Machine Learning","metadata":{}},{"cell_type":"markdown","source":"# Overview\n\nThis notebook uses the Wisconsin Breast Cancer dataset to analyse and predict the diagnosis of a tumour with the help of a Random Forest Classifier using parameters such as radius, area, perimeter, texture and smoothness.\n\n**Dataset:** 569 samples, 30 characteristics describing nucleus features\n\n**Target:** Malignant or Benign\n\n**Tools:** Python, Pandas, Scikit-Learn,Seaborn ","metadata":{}},{"cell_type":"markdown","source":"# Imports and Data Loading","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path=\"/kaggle/input/datasets/mragpavank/breast-cancer/data.csv\"\nrobj=pd.read_csv(path)\n\nrobj.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T12:35:52.072169Z","iopub.execute_input":"2026-05-03T12:35:52.073461Z","iopub.status.idle":"2026-05-03T12:35:52.161563Z","shell.execute_reply.started":"2026-05-03T12:35:52.073412Z","shell.execute_reply":"2026-05-03T12:35:52.160305Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Shape","metadata":{}},{"cell_type":"code","source":"robj.shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T12:36:56.359559Z","iopub.execute_input":"2026-05-03T12:36:56.360838Z","iopub.status.idle":"2026-05-03T12:36:56.367416Z","shell.execute_reply.started":"2026-05-03T12:36:56.360792Z","shell.execute_reply":"2026-05-03T12:36:56.366374Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Info","metadata":{}},{"cell_type":"code","source":"robj.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T12:37:15.009401Z","iopub.execute_input":"2026-05-03T12:37:15.010952Z","iopub.status.idle":"2026-05-03T12:37:15.051671Z","shell.execute_reply.started":"2026-05-03T12:37:15.010794Z","shell.execute_reply":"2026-05-03T12:37:15.050163Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"robj.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T12:37:54.536038Z","iopub.execute_input":"2026-05-03T12:37:54.536341Z","iopub.status.idle":"2026-05-03T12:37:54.600965Z","shell.execute_reply.started":"2026-05-03T12:37:54.536312Z","shell.execute_reply":"2026-05-03T12:37:54.599726Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"robj.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T12:38:47.972464Z","iopub.execute_input":"2026-05-03T12:38:47.973442Z","iopub.status.idle":"2026-05-03T12:38:47.982814Z","shell.execute_reply.started":"2026-05-03T12:38:47.973392Z","shell.execute_reply":"2026-05-03T12:38:47.981771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"robj['diagnosis'].value_counts(normalize=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T12:50:20.259677Z","iopub.execute_input":"2026-05-03T12:50:20.260063Z","iopub.status.idle":"2026-05-03T12:50:20.271705Z","shell.execute_reply.started":"2026-05-03T12:50:20.260032Z","shell.execute_reply":"2026-05-03T12:50:20.270255Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"62% cases are benign and 37% are malignant","metadata":{}},{"cell_type":"markdown","source":"# Creating a Subset with the required parameters","metadata":{}},{"cell_type":"code","source":"robj_subset = robj[['diagnosis', 'radius_mean', 'texture_mean',\n                     'area_mean', 'perimeter_mean', 'smoothness_mean']].copy()\nrobj_subset.head()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Countplot","metadata":{}},{"cell_type":"code","source":"sns.countplot(x='diagnosis', data=robj_subset)\nplt.title(\"Malignant vs Benign Count\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T04:44:25.253701Z","iopub.execute_input":"2026-05-04T04:44:25.254028Z","iopub.status.idle":"2026-05-04T04:44:25.400951Z","shell.execute_reply.started":"2026-05-04T04:44:25.254001Z","shell.execute_reply":"2026-05-04T04:44:25.399825Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Plot shows the count of malignant and benign cases where benign cases are seen to be around 350 and malignant cases around 210. This alone is not enough to predict diagnosis with accuracy.","metadata":{}},{"cell_type":"markdown","source":"# Feature Distributions","metadata":{}},{"cell_type":"code","source":"robj_subset.hist(figsize=(20, 10))\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T04:46:18.223227Z","iopub.execute_input":"2026-05-04T04:46:18.223631Z","iopub.status.idle":"2026-05-04T04:46:19.202160Z","shell.execute_reply.started":"2026-05-04T04:46:18.223577Z","shell.execute_reply":"2026-05-04T04:46:19.200790Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"the radius, area and perimeter histograms are right skewed implying the tumours are of small size in this dataset.","metadata":{}},{"cell_type":"markdown","source":"# Mean Feature values by Diagnosis","metadata":{}},{"cell_type":"code","source":"robj_subset.groupby('diagnosis').mean()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T04:50:41.706225Z","iopub.execute_input":"2026-05-04T04:50:41.706622Z","iopub.status.idle":"2026-05-04T04:50:41.720838Z","shell.execute_reply.started":"2026-05-04T04:50:41.706571Z","shell.execute_reply":"2026-05-04T04:50:41.719674Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The nuclear parameters for malignant cases can be seen to be of higher values than those of benign cases. This shows that malignant tumours are bigger in size compared to benign cases","metadata":{}},{"cell_type":"markdown","source":"# Feature boxplots","metadata":{}},{"cell_type":"code","source":"features = ['radius_mean', 'texture_mean', 'area_mean',\n            'perimeter_mean', 'smoothness_mean']\n \nfor feature in features:\n    plt.figure(figsize=(8, 4))\n    sns.boxplot(x='diagnosis', y=feature, data=robj_subset)\n    plt.title(f'Distribution of {feature} by Diagnosis')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T04:57:57.365547Z","iopub.execute_input":"2026-05-04T04:57:57.366338Z","iopub.status.idle":"2026-05-04T04:57:58.069947Z","shell.execute_reply.started":"2026-05-04T04:57:57.366221Z","shell.execute_reply":"2026-05-04T04:57:58.068863Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Radius, area and perimeter have almost no overlap between malignant and benign cases and can possibly be used as parameters for the prediction of malignant and benign tumours in this dataset.","metadata":{}},{"cell_type":"markdown","source":"# Correlation Heatmap","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(20,20))\nsns.heatmap(robj_subset.drop(columns='diagnosis').corr(),annot=True,fmt='.1f',cmap='coolwarm')\nplt.title(\"Feature Correlation Matrix\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:08:57.499233Z","iopub.execute_input":"2026-05-04T05:08:57.499642Z","iopub.status.idle":"2026-05-04T05:08:57.872654Z","shell.execute_reply.started":"2026-05-04T05:08:57.499563Z","shell.execute_reply":"2026-05-04T05:08:57.871571Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Machine Learning Model","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.metrics import accuracy_score, confusion_matrix, classification_report","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:09:50.484460Z","iopub.execute_input":"2026-05-04T05:09:50.484846Z","iopub.status.idle":"2026-05-04T05:09:50.490910Z","shell.execute_reply.started":"2026-05-04T05:09:50.484814Z","shell.execute_reply":"2026-05-04T05:09:50.489688Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"robj['diagnosis_encoded'] = robj['diagnosis'].map({'M': 1, 'B': 0})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:10:09.298374Z","iopub.execute_input":"2026-05-04T05:10:09.298804Z","iopub.status.idle":"2026-05-04T05:10:09.306504Z","shell.execute_reply.started":"2026-05-04T05:10:09.298760Z","shell.execute_reply":"2026-05-04T05:10:09.305074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = robj[['radius_mean', 'texture_mean', 'area_mean','perimeter_mean', 'smoothness_mean']]\nY = robj['diagnosis_encoded']\n \nX_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:10:51.405884Z","iopub.execute_input":"2026-05-04T05:10:51.406252Z","iopub.status.idle":"2026-05-04T05:10:51.415255Z","shell.execute_reply.started":"2026-05-04T05:10:51.406217Z","shell.execute_reply":"2026-05-04T05:10:51.413842Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The model is to learn from 80% of the cases and test its predictions on 20% of cases","metadata":{}},{"cell_type":"markdown","source":"# Model Training","metadata":{}},{"cell_type":"code","source":"model=RandomForestClassifier(n_estimators=100,random_state=42)\nmodel.fit(X_train,Y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:12:41.371727Z","iopub.execute_input":"2026-05-04T05:12:41.372083Z","iopub.status.idle":"2026-05-04T05:12:41.611971Z","shell.execute_reply.started":"2026-05-04T05:12:41.372052Z","shell.execute_reply":"2026-05-04T05:12:41.610650Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Y_pred=model.predict(X_test)\nprint(f'Accuracy:{accuracy_score(Y_test,Y_pred):.2f}')\nprint(classification_report(Y_test,Y_pred,target_names=['Benign','Malignant']))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:16:43.949918Z","iopub.execute_input":"2026-05-04T05:16:43.950257Z","iopub.status.idle":"2026-05-04T05:16:43.988578Z","shell.execute_reply.started":"2026-05-04T05:16:43.950226Z","shell.execute_reply":"2026-05-04T05:16:43.987525Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The model shows an accuracy of 94% and malignant recall of 95%","metadata":{}},{"cell_type":"code","source":"cm=confusion_matrix(Y_test,Y_pred)\nsns.heatmap(cm,annot=True,fmt='d',cmap='Greens',xticklabels=['Benign','Malignant'],yticklabels=['Benign','Malignant'])\nplt.title(\"Confusion Matrix\")\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"Actual\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:21:09.292185Z","iopub.execute_input":"2026-05-04T05:21:09.292611Z","iopub.status.idle":"2026-05-04T05:21:09.462804Z","shell.execute_reply.started":"2026-05-04T05:21:09.292555Z","shell.execute_reply":"2026-05-04T05:21:09.461558Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"66 cases have been righthfully predicted to be benign and 41 cases to be malignant. 2 malignant cases have been mispredicted as benign(false negatives) and 5 benign cases have been predicted to be malignant(false positives)","metadata":{}},{"cell_type":"markdown","source":"# Model Importance","metadata":{}},{"cell_type":"code","source":"importances = pd.Series(model.feature_importances_,index=X.columns).sort_values(ascending=False)\nsns.barplot(x=importances.values, y=importances.index)\nplt.title('Feature Importance')\nplt.xlabel('Importance Score')\nplt.ylabel('')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-04T05:44:30.626961Z","iopub.execute_input":"2026-05-04T05:44:30.627315Z","iopub.status.idle":"2026-05-04T05:44:30.823777Z","shell.execute_reply.started":"2026-05-04T05:44:30.627285Z","shell.execute_reply":"2026-05-04T05:44:30.822550Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Perimeter, area and radius are seen to be strong predictors of benign and malignant tumour identification whereas texture and smoothness rank low.","metadata":{}},{"cell_type":"markdown","source":"# Conclusion\n\nUsing only 5 morphological features the model was able to learn and predict the diagnoses with an accuracy of 94% and a malignant recall of 95%. Further work could explore using all 30 parameters as predictors.","metadata":{}}]}