Logistic regression turns one weighted score into one probability, which is enough for a yes-or-no answer. To choose among k classes, give every class its own weights and its own score, and let the scores compete. This model is softmax regression, also called multinomial logistic regression.
For a row x=(x1,…,xd), each class c=0,1,…,k−1 gets a score and then a probability:
zc=bc+j=1∑dWc,jxjpc=ez0+ez1+⋯+ezk−1ezc
The pc are positive and add up to 1. Training lowers the cross-entropy cost: the average over all n rows of −lnpy, where y is the row's true class. Its gradient has a tidy form. For one row, the error of class c is
ec=pc−{10if c=yotherwise
The gradient for Wc,j is the average of ecxj over all rows, and the gradient for bc is the average of ec.
Task: write train_softmax(X, y, k, lr, steps). Start with every weight and bias at 0, then run steps updates of batch gradient descent, each one moving every weight and bias by lr times its gradient, downhill:
Wc,j←Wc,j−lr×(gradient for Wc,j)bc←bc−lr×(gradient for bc)
X is a list of n rows of d numbers. y holds each row's class, an integer from 0 to k - 1. A class may have no rows at all.
- Every update uses all the rows, and every gradient in one update is computed from the weights as they were at the start of that update.
- Return a tuple
(W, b): W is a list of k lists of d weights and b is a list of k biases, all rounded to 4 decimal places.
- One test has features in the hundreds, which pushes some scores into the tens of thousands. ez overflows long before that, so compute the probabilities in a way that never raises e to a large positive power.