1
2
3
4
5
6
7
8
9 """Penalized logistic regression classifier."""
10
11 __docformat__ = 'restructuredtext'
12
13
14 import numpy as N
15
16 from mvpa.misc.exceptions import ConvergenceError
17 from mvpa.clfs.base import Classifier, FailedToTrainError
18
19 if __debug__:
20 from mvpa.base import debug
21
22
23 -class PLR(Classifier):
24 """Penalized logistic regression `Classifier`.
25 """
26
27 _clf_internals = [ 'plr', 'binary', 'linear' ]
28
29 - def __init__(self, lm=1, criterion=1, reduced=0.0, maxiter=20, **kwargs):
30 """
31 Initialize a penalized logistic regression analysis
32
33 :Parameters:
34 lm : int
35 the penalty term lambda.
36 criterion : int
37 the criterion applied to judge convergence.
38 reduced : float
39 if not 0, the rank of the data is reduced before
40 performing the calculations. In that case, reduce is taken
41 as the fraction of the first singular value, at which a
42 dimension is not considered significant anymore. A
43 reasonable criterion is reduced=0.01
44 maxiter : int
45 maximum number of iterations. If no convergence occurs
46 after this number of iterations, an exception is raised.
47
48 """
49
50 Classifier.__init__(self, **kwargs)
51
52 self.__lm = lm
53 self.__criterion = criterion
54 self.__reduced = reduced
55 self.__maxiter = maxiter
56
57
59 """String summary over the object
60 """
61 return """PLR(lm=%f, criterion=%d, reduced=%s, maxiter=%d, enable_states=%s)""" % \
62 (self.__lm, self.__criterion, self.__reduced, self.__maxiter,
63 str(self.states.enabled))
64
65
67 """Train the classifier using `data` (`Dataset`).
68 """
69
70 X = data.samples.T
71 d = data.labels
72 if set(d) != set([0, 1]):
73 raise ValueError, \
74 "Regressors for logistic regression should be [0,1]. Got %s" \
75 %(set(d),)
76
77 if self.__reduced != 0 :
78
79 from scipy.linalg import svd
80
81
82
83 U, S, V = svd(X.T)
84 if S[0] == 0:
85 raise FailedToTrainError(
86 "Data provided to PLR seems to be degenerate -- "
87 "0-th singular value is 0")
88 S /= S[0]
89 V = N.matrix(V[:, :N.max(N.where(S > self.__reduced)) + 1])
90
91 X = (X.T * V).T
92
93 nfeatures, npatterns = X.shape
94
95
96 w = N.matrix(N.zeros( (nfeatures + 1, 1), 'd'))
97
98 dw = N.matrix(N.ones( (nfeatures + 1, 1), 'd'))
99
100 X = N.matrix( \
101 N.concatenate((X, N.ones((1, npatterns), 'd')), 0) \
102 )
103 p = N.matrix(N.zeros((1, npatterns), 'd'))
104
105 Lambda = self.__lm * N.identity(nfeatures + 1, 'd')
106 Lambda[nfeatures, nfeatures] = 0
107
108 g = N.matrix(N.zeros((nfeatures + 1, 1), 'd'))
109
110 H = N.matrix(N.identity(nfeatures + 1, 'd'))
111
112
113 k = 0
114 while N.sum(N.ravel(dw.A ** 2)) > self.__criterion:
115 p[:, :] = self.__f(w.T * X)
116 g[:, :] = X * (d - p).T - Lambda * w
117 H[:, :] = X * N.diag(p.A1 * (1 - p.A1)) * X.T + Lambda
118 dw[:, :] = H.I * g
119 w += dw
120 k += 1
121 if k > self.__maxiter:
122 raise ConvergenceError, \
123 "More than %d Iterations without convergence" % \
124 (self.__maxiter)
125
126 if __debug__:
127 debug("PLR", \
128 "PLR converged after %d steps. Error: %g" % \
129 (k, N.sum(N.ravel(dw.A ** 2))))
130
131 if self.__reduced:
132
133
134 self.w = V * w[:-1]
135 self.offset = w[-1]
136 else:
137 self.w = w[:-1]
138 self.offset = w[-1]
139
140
142 """This is the logistic function f, that is used for determination of
143 the vector w"""
144 return 1. / (1 + N.exp(-y))
145
146
166