| 22 | |
| 23 | |
| 24 | class LogisticRegression: |
| 25 | def __init__(self): |
| 26 | pass |
| 27 | |
| 28 | def fit(self, X, Y, V=None, K=None, D=50, lr=1e-1, mu=0.99, batch_sz=100, epochs=6): |
| 29 | if V is None: |
| 30 | V = len(set(X)) |
| 31 | if K is None: |
| 32 | K = len(set(Y)) |
| 33 | N = len(X) |
| 34 | |
| 35 | W = np.random.randn(V, K) / np.sqrt(V + K) |
| 36 | b = np.zeros(K) |
| 37 | self.W = theano.shared(W) |
| 38 | self.b = theano.shared(b) |
| 39 | self.params = [self.W, self.b] |
| 40 | |
| 41 | thX = T.ivector('X') |
| 42 | thY = T.ivector('Y') |
| 43 | |
| 44 | py_x = T.nnet.softmax(self.W[thX] + self.b) |
| 45 | prediction = T.argmax(py_x, axis=1) |
| 46 | |
| 47 | cost = -T.mean(T.log(py_x[T.arange(thY.shape[0]), thY])) |
| 48 | grads = T.grad(cost, self.params) |
| 49 | dparams = [theano.shared(p.get_value()*0) for p in self.params] |
| 50 | self.cost_predict_op = theano.function( |
| 51 | inputs=[thX, thY], |
| 52 | outputs=[cost, prediction], |
| 53 | allow_input_downcast=True, |
| 54 | ) |
| 55 | |
| 56 | updates = [ |
| 57 | (p, p + mu*dp - lr*g) for p, dp, g in zip(self.params, dparams, grads) |
| 58 | ] + [ |
| 59 | (dp, mu*dp - lr*g) for dp, g in zip(dparams, grads) |
| 60 | ] |
| 61 | train_op = theano.function( |
| 62 | inputs=[thX, thY], |
| 63 | outputs=[cost, prediction], |
| 64 | updates=updates, |
| 65 | allow_input_downcast=True |
| 66 | ) |
| 67 | |
| 68 | costs = [] |
| 69 | n_batches = N // batch_sz |
| 70 | for i in range(epochs): |
| 71 | X, Y = shuffle(X, Y) |
| 72 | print("epoch:", i) |
| 73 | for j in range(n_batches): |
| 74 | Xbatch = X[j*batch_sz:(j*batch_sz + batch_sz)] |
| 75 | Ybatch = Y[j*batch_sz:(j*batch_sz + batch_sz)] |
| 76 | |
| 77 | c, p = train_op(Xbatch, Ybatch) |
| 78 | costs.append(c) |
| 79 | if j % 200 == 0: |
| 80 | print( |
| 81 | "i:", i, "j:", j, |
no outgoing calls
no test coverage detected