-
Notifications
You must be signed in to change notification settings - Fork 0
/
lab3.py
295 lines (189 loc) · 9.9 KB
/
lab3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#!/usr/bin/python
# coding: utf-8
# # Lab 3: Bayes Classifier and Boosting
# ## Jupyter notebooks
#
# In this lab, you can use Jupyter <https://jupyter.org/> to get a nice layout of your code and plots in one document. However, you may also use Python as usual, without Jupyter.
#
# If you have Python and pip, you can install Jupyter with `sudo pip install jupyter`. Otherwise you can follow the instruction on <http://jupyter.readthedocs.org/en/latest/install.html>.
#
# And that is everything you need! Now use a terminal to go into the folder with the provided lab files. Then run `jupyter notebook` to start a session in that folder. Click `lab3.ipynb` in the browser window that appeared to start this very notebook. You should click on the cells in order and either press `ctrl+enter` or `run cell` in the toolbar above to evaluate all the expressions.
# ## Import the libraries
#
# In Jupyter, select the cell below and press `ctrl + enter` to import the needed libraries.
# Check out `labfuns.py` if you are interested in the details.
import numpy as np
from scipy import misc
from imp import reload
from labfuns import *
import random
# ## Bayes classifier functions to implement
#
# The lab descriptions state what each function should do.
# NOTE: you do not need to handle the W argument for this part!
# in: labels - N vector of class labels
# out: prior - C x 1 vector of class priors
def computePrior(labels, W=None):
Npts = labels.shape[0]
if W is None:
W = np.ones((Npts,1))/Npts
else:
assert(W.shape[0] == Npts)
classes = np.unique(labels)
Nclasses = np.size(classes)
prior = np.zeros((Nclasses,1))
# TODO: compute the values of prior for each class!
# ==========================
# ==========================
return prior
# NOTE: you do not need to handle the W argument for this part!
# in: X - N x d matrix of N data points
# labels - N vector of class labels
# out: mu - C x d matrix of class means (mu[i] - class i mean)
# sigma - C x d x d matrix of class covariances (sigma[i] - class i sigma)
def mlParams(X, labels, W=None):
assert(X.shape[0]==labels.shape[0])
Npts,Ndims = np.shape(X)
classes = np.unique(labels)
Nclasses = np.size(classes)
if W is None:
W = np.ones((Npts,1))/float(Npts)
mu = np.zeros((Nclasses,Ndims))
sigma = np.zeros((Nclasses,Ndims,Ndims))
# TODO: fill in the code to compute mu and sigma!
# ==========================
# ==========================
return mu, sigma
# in: X - N x d matrix of M data points
# prior - C x 1 matrix of class priors
# mu - C x d matrix of class means (mu[i] - class i mean)
# sigma - C x d x d matrix of class covariances (sigma[i] - class i sigma)
# out: h - N vector of class predictions for test points
def classifyBayes(X, prior, mu, sigma):
Npts = X.shape[0]
Nclasses,Ndims = np.shape(mu)
logProb = np.zeros((Nclasses, Npts))
# TODO: fill in the code to compute the log posterior logProb!
# ==========================
# ==========================
# one possible way of finding max a-posteriori once
# you have computed the log posterior
h = np.argmax(logProb,axis=0)
return h
# The implemented functions can now be summarized into the `BayesClassifier` class, which we will use later to test the classifier, no need to add anything else here:
# NOTE: no need to touch this
class BayesClassifier(object):
def __init__(self):
self.trained = False
def trainClassifier(self, X, labels, W=None):
rtn = BayesClassifier()
rtn.prior = computePrior(labels, W)
rtn.mu, rtn.sigma = mlParams(X, labels, W)
rtn.trained = True
return rtn
def classify(self, X):
return classifyBayes(X, self.prior, self.mu, self.sigma)
# ## Test the Maximum Likelihood estimates
#
# Call `genBlobs` and `plotGaussian` to verify your estimates.
X, labels = genBlobs(centers=5)
mu, sigma = mlParams(X,labels)
plotGaussian(X,labels,mu,sigma)
# Call the `testClassifier` and `plotBoundary` functions for this part.
#testClassifier(BayesClassifier(), dataset='iris', split=0.7)
#testClassifier(BayesClassifier(), dataset='vowel', split=0.7)
#plotBoundary(BayesClassifier(), dataset='iris',split=0.7)
# ## Boosting functions to implement
#
# The lab descriptions state what each function should do.
# in: base_classifier - a classifier of the type that we will boost, e.g. BayesClassifier
# X - N x d matrix of N data points
# labels - N vector of class labels
# T - number of boosting iterations
# out: classifiers - (maximum) length T Python list of trained classifiers
# alphas - (maximum) length T Python list of vote weights
def trainBoost(base_classifier, X, labels, T=10):
# these will come in handy later on
Npts,Ndims = np.shape(X)
classifiers = [] # append new classifiers to this list
alphas = [] # append the vote weight of the classifiers to this list
# The weights for the first iteration
wCur = np.ones((Npts,1))/float(Npts)
for i_iter in range(0, T):
# a new classifier can be trained like this, given the current weights
classifiers.append(base_classifier.trainClassifier(X, labels, wCur))
# do classification for each point
vote = classifiers[-1].classify(X)
# TODO: Fill in the rest, construct the alphas etc.
# ==========================
# alphas.append(alpha) # you will need to append the new alpha
# ==========================
return classifiers, alphas
# in: X - N x d matrix of N data points
# classifiers - (maximum) length T Python list of trained classifiers as above
# alphas - (maximum) length T Python list of vote weights
# Nclasses - the number of different classes
# out: yPred - N vector of class predictions for test points
def classifyBoost(X, classifiers, alphas, Nclasses):
Npts = X.shape[0]
Ncomps = len(classifiers)
# if we only have one classifier, we may just classify directly
if Ncomps == 1:
return classifiers[0].classify(X)
else:
votes = np.zeros((Npts,Nclasses))
# TODO: implement classificiation when we have trained several classifiers!
# here we can do it by filling in the votes vector with weighted votes
# ==========================
# ==========================
# one way to compute yPred after accumulating the votes
return np.argmax(votes,axis=1)
# The implemented functions can now be summarized another classifer, the `BoostClassifier` class. This class enables boosting different types of classifiers by initializing it with the `base_classifier` argument. No need to add anything here.
# NOTE: no need to touch this
class BoostClassifier(object):
def __init__(self, base_classifier, T=10):
self.base_classifier = base_classifier
self.T = T
self.trained = False
def trainClassifier(self, X, labels):
rtn = BoostClassifier(self.base_classifier, self.T)
rtn.nbr_classes = np.size(np.unique(labels))
rtn.classifiers, rtn.alphas = trainBoost(self.base_classifier, X, labels, self.T)
rtn.trained = True
return rtn
def classify(self, X):
return classifyBoost(X, self.classifiers, self.alphas, self.nbr_classes)
# ## Run some experiments
#
# Call the `testClassifier` and `plotBoundary` functions for this part.
#testClassifier(BoostClassifier(BayesClassifier(), T=10), dataset='iris',split=0.7)
#testClassifier(BoostClassifier(BayesClassifier(), T=10), dataset='vowel',split=0.7)
#plotBoundary(BoostClassifier(BayesClassifier()), dataset='iris',split=0.7)
# Now repeat the steps with a decision tree classifier.
#testClassifier(DecisionTreeClassifier(), dataset='iris', split=0.7)
#testClassifier(BoostClassifier(DecisionTreeClassifier(), T=10), dataset='iris',split=0.7)
#testClassifier(DecisionTreeClassifier(), dataset='vowel',split=0.7)
#testClassifier(BoostClassifier(DecisionTreeClassifier(), T=10), dataset='vowel',split=0.7)
#plotBoundary(DecisionTreeClassifier(), dataset='iris',split=0.7)
#plotBoundary(BoostClassifier(DecisionTreeClassifier(), T=10), dataset='iris',split=0.7)
# ## Bonus: Visualize faces classified using boosted decision trees
#
# Note that this part of the assignment is completely voluntary! First, let's check how a boosted decision tree classifier performs on the olivetti data. Note that we need to reduce the dimension a bit using PCA, as the original dimension of the image vectors is `64 x 64 = 4096` elements.
#testClassifier(BayesClassifier(), dataset='olivetti',split=0.7, dim=20)
#testClassifier(BoostClassifier(DecisionTreeClassifier(), T=10), dataset='olivetti',split=0.7, dim=20)
# You should get an accuracy around 70%. If you wish, you can compare this with using pure decision trees or a boosted bayes classifier. Not too bad, now let's try and classify a face as belonging to one of 40 persons!
#X,y,pcadim = fetchDataset('olivetti') # fetch the olivetti data
#xTr,yTr,xTe,yTe,trIdx,teIdx = trteSplitEven(X,y,0.7) # split into training and testing
#pca = decomposition.PCA(n_components=20) # use PCA to reduce the dimension to 20
#pca.fit(xTr) # use training data to fit the transform
#xTrpca = pca.transform(xTr) # apply on training data
#xTepca = pca.transform(xTe) # apply on test data
# use our pre-defined decision tree classifier together with the implemented
# boosting to classify data points in the training data
#classifier = BoostClassifier(DecisionTreeClassifier(), T=10).trainClassifier(xTrpca, yTr)
#yPr = classifier.classify(xTepca)
# choose a test point to visualize
#testind = random.randint(0, xTe.shape[0]-1)
# visualize the test point together with the training points used to train
# the class that the test point was classified to belong to
#visualizeOlivettiVectors(xTr[yTr == yPr[testind],:], xTe[testind,:])