| 70 | return x * (x > 0) |
| 71 | |
| 72 | class ANN: |
| 73 | def __init__(self, D, M, K, f=relu): |
| 74 | self.D = D |
| 75 | self.M = M |
| 76 | self.K = K |
| 77 | self.f = f |
| 78 | |
| 79 | def init(self): |
| 80 | D, M, K = self.D, self.M, self.K |
| 81 | self.W1 = np.random.randn(D, M) / np.sqrt(D) |
| 82 | # self.W1 = np.zeros((D, M)) |
| 83 | self.b1 = np.zeros(M) |
| 84 | self.W2 = np.random.randn(M, K) / np.sqrt(M) |
| 85 | # self.W2 = np.zeros((M, K)) |
| 86 | self.b2 = np.zeros(K) |
| 87 | |
| 88 | def forward(self, X): |
| 89 | Z = self.f(X.dot(self.W1) + self.b1) |
| 90 | return softmax(Z.dot(self.W2) + self.b2) |
| 91 | |
| 92 | def sample_action(self, x): |
| 93 | # assume input is a single state of size (D,) |
| 94 | # first make it (N, D) to fit ML conventions |
| 95 | X = np.atleast_2d(x) |
| 96 | P = self.forward(X) |
| 97 | p = P[0] # the first row |
| 98 | # return np.random.choice(len(p), p=p) |
| 99 | return np.argmax(p) |
| 100 | |
| 101 | def score(self, X, Y): |
| 102 | P = np.argmax(self.forward(X), axis=1) |
| 103 | return np.mean(Y == P) |
| 104 | |
| 105 | def get_params(self): |
| 106 | # return a flat array of parameters |
| 107 | return np.concatenate([self.W1.flatten(), self.b1, self.W2.flatten(), self.b2]) |
| 108 | |
| 109 | def get_params_dict(self): |
| 110 | return { |
| 111 | 'W1': self.W1, |
| 112 | 'b1': self.b1, |
| 113 | 'W2': self.W2, |
| 114 | 'b2': self.b2, |
| 115 | } |
| 116 | |
| 117 | def set_params(self, params): |
| 118 | # params is a flat list |
| 119 | # unflatten into individual weights |
| 120 | D, M, K = self.D, self.M, self.K |
| 121 | self.W1 = params[:D * M].reshape(D, M) |
| 122 | self.b1 = params[D * M:D * M + M] |
| 123 | self.W2 = params[D * M + M:D * M + M + M * K].reshape(M, K) |
| 124 | self.b2 = params[-K:] |
| 125 | |
| 126 | |
| 127 | |