The provided data gives several physical metrics regarding breast cancer tumors with the goal of predicting malignancy. The model made is simple, requiring only 3 predictors: radius mean, concavity worst, and symmetry worst. Based on our test set, we expect our model to predict malignancy with a 94% accuracy in the real world. The model also tells us that there is a positive relationship between concavity worst and symmetry worst with malignancy.

The provided data was scaled using min max scaler, and fed into a logistic model. The logistic model used a l1 penalty with a penalty coefficient of 0.01 (C = 100).

The predictors used for the model were radius mean, concavity worst, and symmetry worst. Radius mean and concavity worst are correlated, so an interaction term was created. Radius mean and the interaction term were determined not statistically significant. However getting rid of them slightly affects the accuracy, and the radius mean is on the cusp of being significant, so they were kept within the model.

The data was split into a 70% train set and 30% test set, and below are the performances:

Train Performance

- Accuracy: 96%
- Sensitivity: 94%
- Specificity: 97%

Test Peformance

- Accuracy: 94%
- Sensitivity: 89%
- Specificity: 97%

There is some dropoff of sensitivity between the train and test sets. If this is an issue when the model is deployed, it may be good to consider adding a slight penalty to False Negatives.

A random forest was also created and performed at the same level as the logistic regression. However, I find the logistic model preferable due to its interpretability.

Loading in Data with Header

Performing exploratory data analysis on the data

Classes are slightly unbalanced, and we have a limited number of records.

Loading output library...

Loading output library...

The mean for both smoothness and compactness is greater than the median. This is due to the outliers that are greater than both the medians within the distributions. In the distributions below the median line is blue and the mean line is green.

Loading output library...

Loading output library...

Loading output library...

Loading output library...

Below I used the function from one of the labs to create a bootstrap sample. The function takes a dataframe, converts it into a list of dictionaries, takes a random sample, and then converts it back to a dataframe.

Loading output library...

Using a minmax scaler to help scale the data. This is to help prevent any one variable from influencing the model due to its scale.

Making the diagnosis column into a binary

The variables radius_mean, perimeter_mean, concavity_worst, symmetry_worst, and fractal_dimension_mean all look like they have a positive correlation with malignancy. Below you can see the violin plot on the right is higher in each of the graphs.

There were other correlated variables, but I decided only to focus on either the mean or the worst of any set (i.e. if radius mean and radius std error correlated with malignancy, I would just plot radius mean).

One issue with the data is that most of the variables are highly correlated with each other, causing issues for any models that assume independence.

Loading output library...

Loading output library...

Loading output library...

Loading output library...

Loading output library...

Loading output library...

Loading output library...

One of the models I went with is a logistic regression, since it is a relatively familiar model and the coefficients can tell us how the features affect the probability of malignancy.

One of the drawbacks is that I have to be selective with my features, because if they are highly correlated it will introduce multicollinearity, which will affect my results. Also the data is scaled, so I will not be able to produce useful odds ratios from the coefficients.

For this model I will select radius mean, concavity worst, and symmetry worst. Radius mean and concavity worst are highly correlated, so I will use an interaction term as well.

To prevent overfitting I will let grid search optimize the regularization coefficient and whether I should use l1 or l2 regularization.

Loading output library...

Here is the best model chosen by grid search. The regularization level C is 100, and the regularization penalty is l1.

Loading output library...

The intercept and coefficients for the best model are below.

I did the same fit using stats models to check the confidence intervals of each predictor. Some of the parameters within stats models are different, and for that reason the coefficients do not exactly equal the output form scikit-learn.

Notice that radius mean and the radius mean concavity worst interaction term are not statistically significant. However, when I remove them from the model, I do lose a couple of points in accuracy, and for that reason I left them in the model.

Radius mean is on the cusp of being significant, and if I were to decrease my confidence to 90% it probably would be significant.

Loading output library...

Below is the evaluation on the training set. There is a 96% accuracy, a 94% sensitivity, and a 97% specificity.

The ROC Curve is far from the dashed line, which is exactly what we want.

Loading output library...

Below is the evaluation on the testing set. There is a 94% accuracy, a 89% sensitivity, and a 97% specificity.

We also get a nice ROC curve here.

Loading output library...

This model performs very nicely. It is simple because it only requires three variables (plus an interaction term), and it performs consistently between the train and test sets. We can also say that increases in concavity worst and symmetry worst lead to an increased probability of malignancy (Although, I'm reluctant to say either or for radius mean, because of conflicting coefficient signs between it and the interaction term, and it not being statistically significant).

The only drawback is that we lose some sensitivity with the test set. If we were to deploy this model we may consider adding a slight penalty to False Negatives.

The other model I use is a random forest. I do not have to worry about independence of predictors, so I'm going to throw in all the variables that seem to correlate with malignancy.

To help control for overfitting, I will have grid search choose a max depth between 1 and 5 therefore preventing the trees from growing too large.

Loading output library...

Here our forest makes at least 4 levels of splits, and there are 50 trees aggregated within the forest.

Loading output library...

Below you can see feature importances, where concavity worst is the most important feature, and symmetry worst is the least important.

Loading output library...

Loading output library...

In the train set we have a 98% accuracy rate, a 95% sensitivity rate, and a 99% specificity rate.

The ROC curve here shows a nice separation of classes as well.

Loading output library...

In our test set we get a 94% accuracy rate, with a 89% sensitivity, and a 96% specificity.

Loading output library...

The random forest also performed very nicely. We did have some dropoff in accuracy from 98% in the train set to 94% in the test set. The test set shows that it may perform at the same level as the logistic regression.

However, you cannot make the same inferences with the random forest as you can with the logistic regression. You can tell what features are important, but you are unable to tell if they positively or negatively affect the probability of malignancy.

For this reason and its simplicity, I would go with the logistic model.