Skip to main content

Training a Heart Disease Classifier

As I begin writing this post I realize that we're not training a heart disease predictor, per se, as the classification task at hand isn't really to divine the onset of heart disease in the distant future. Rather, we're really training a heart disease classifier that identifies heart disease given test results, vital measurements, and demographic information. While much less cool than a predictor, this is still a pretty difficult task and I'm certain the definition of "heart disease" might present some aspects of ambiguity and subjectivity between cardiologists. To illustrate the difficulty of this task, you might ask yourself: if you were given the sex, angina status, heart rate measurements, cholesterol measurements, and EKG results of a patient, would you be able to diagnose that patient as having heart disease?

Anyways, let's go ahead and train this network. That can be done with these lines of code. Execution of these lines of code takes about 20 minutes on an i7-6500U.
We can see that there are a bunch of parameters for this model-construction function "mx.mlp" and I'll explain those.  The data and label parameters contain the matrices of inputs and ground truth values of the training set. The hidden node parameter is a vector of integers that specifies how many nodes are in each hidden layer. In this case, we're building a network with two hidden layers of 10 units each. The out_node parameter specifies the number of output nodes: 2, because we're regressing the probability of the presence of heart disease and the presence of a lack of heart disease. The out_activation parameter specifies the activation function for the output. In this case, we're using softmax, which is essentially a multiclass adaptation of the logistic regression function. Finally, we have our number of rounds, our batch size (we're doing full-batch learning), our learning rate, and our momentum.

These parameters have been tweaked while training to converge upon a decent solution.

You might notice that we're using an activation function that might be a little strange. This "softrelu" is like the rectified linear activation function except that it asymptotically approaches zero as the input tends to negative infinity. This is useful because it's smooth and therefore differentiable. Also, ReLU's have this terrible defect that I was experiencing while attempting to train this network where they have a chance at dying completely if they reach a point where all inputs to the ReLU's are less than 0 (weights are negative and inputs are positive). If a ReLU reaches this situation, it effectively can only output 0, as the derivative of the ReLU activation function can only be positive given positive inputs.

Okay, so after the training has been conducted, we can look at the results. The R console should show:
Towards the end, we can see that training accuracy was nearing 90%. That's pretty promising. Even though this accuracy is lower than what we saw on the iris dataset, it's important to keep in mind that this is a much more difficult classification task and presents a facade of a very complex physiological system.

Let's continue in the next post to evaluate actually how good this model performs on the test set and we'll also wrap things up.

Comments

Popular posts from this blog

Classifying Flowers Part 1: Data

Everybody loves plants. So we'll continue our descent by building a neural network that can do something with plants. This construct will be able to take characteristics that describe a plant and, if we're good enough, hopefully the neural network will be able to tell us with accuracy what type of plant it is. To do this, we'll use the Iris flowers dataset, which contains 150 samples of 3 different species (50 samples each). The species in this dataset are Iris setosa, Iris versicolor, and Iris virginica. The dataset can be found at the following links. Data:  https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data ReadME:  https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.names Here's a screenshot of the data we'll be working with: Initially, this data doesn't look too exciting and if it at all confuses you, you're perfectly normal. But we can figure some immediate information just from looking at the format ...

Classifying Flowers Part 2: Training and Evaluation

In the previous post, we fiddled with data and set out for an ambitious task of classifying plants. We ended that post after having downloaded, prepared, and partitioned our data, resulting two non-overlapping sets of data: a test set and a training set. We'll continue now by building, training, and evaluating a neural network to classify these flowers. First, we'll need to separate the values that we'll use as input to the network from the values we're intending to use as the output from the network. In other words, we need to place all the sepal and petal widths and lengths into a bag that the network can read, and all the species corresponding to the individual sets of sepal and petal widths and lengths into another bag. That way, when the network trains, it only takes into account the 4 inputs. When it produces an output, we can use the other bag (the one with species inside) to see if the network has predicted the species correctly. Before doing that, we'...

Evaluating our Heart Disease Classifier

Let's continue our descent by evaluating how good our heart disease classifier is. We can do this by generating predictions on the test set and see how the predictions compare to the test set's ground truth labels. That can be done with the following lines of code: At the bottom we can see that the classifier predicted 24 true negatives, 9 false positives, 8 false negatives, and 19 true positives. That's pretty okay. There is obviously some inaccuracy in the predictions, but let's calculate the accuracy anyways. (24+19)/(24+19+8+9)=71.6. So the test accuracy was 71.6, while, if you recall from the last post, the training accuracy was nearing 90%. This disparity between training and testing accuracy is a result of overfitting. Essentially, 50,000 training loops was too much training for this little of data. The resulting network overfit to the noise inherent in the training data and, as a result, failed to generalize as well on the test set. Therefore, the testing...