7 class KnnWeightedLearner(Orange
.classification
.Learner
):
8 def __new__(cls
, examples
=None, **kwargs
):
9 learner
= Orange
.classification
.Learner
.__new
__(cls
, **kwargs
)
11 # force init and return classifier
12 learner
.__init
__(**kwargs
)
13 return learner
.__call
__(examples
)
21 distance_constructor
=Orange
.distance
.Euclidean(),
26 self
.distance_constructor
= distance_constructor
28 self
.exp_weight
= exp_weight
30 def __call__(self
, data
, weight
=0):
31 assert isinstance(data
.domain
.class_var
, Orange
.feature
.Continuous
)
33 if not data
.domain
.class_var
:
34 raise ValueError('classless domain')
36 fnc
= Orange
.classification
.knn
.FindNearestConstructor()
37 fnc
.distance_constructor
= self
.distance_constructor
38 did
= Orange
.feature
.Descriptor
.new_meta_id()
40 fn
= fnc(data
, 0, did
)
44 k
= int(math
.sqrt( len(data
)))
46 return KnnWeightedClassifier(data
.domain
, k
, fn
, self
.alpha
, self
.exp_weight
)
48 ## FIXME Orange.classification.Classifier (which should be there)
49 ## is commented because if it is not, pickling does not work...
50 class KnnWeightedClassifier
: #(Orange.classification.Classifier):
51 def __init__(self
, domain
, k
, find_nearest
, alpha
, exp_weight
):
53 self
.domain_f
= Orange
.data
.Domain(domain
.features
)
55 self
.find_nearest
= find_nearest
57 self
.exp_weight
= exp_weight
60 def __call__(self
, instance
, resultType
=Orange
.core
.GetValue
):
61 if not instance
.domain
!= self
.domain_f
:
62 raise ValueError("instance has wrong domain")
67 nbs
= self
.find_nearest(instance
, self
.k
)
70 dsts
= numpy
.array( [ nb
[self
.find_nearest
.distance_ID
]
73 clss
= numpy
.array( [ nb
.get_class()
76 #logging.warn('0 in distances, add epsilon')
80 if not self
.exp_weight
:
81 # inversely proportional
82 w
= dsts
** ( - self
.alpha
)
84 assert 0.0 < self
.alpha
< 1.0
86 w
= self
.alpha
** dsts
91 res
= (w
* clss
).sum()
93 value
= self
.domain
.class_var(res
)
95 dist
= Orange
.statistics
.distribution
.Continuous(self
.domain
.class_var
)
98 if resultType
== Orange
.core
.GetValue
:
100 if resultType
== Orange
.core
.GetProbabilities
:
105 ## tests and examples
109 data
= Orange
.data
.Table("housing")
111 from fann_neural
import FannNeuralLearner
114 KnnWeightedLearner( k
=4, alpha
=2 ),
115 KnnWeightedLearner( k
=4, alpha
=1 ),
116 KnnWeightedLearner( k
=4, alpha
=0 ),
117 Orange
.classification
.knn
.kNNLearner(k
=4, name
='knn 4'),
118 Orange
.classification
.knn
.kNNLearner(k
=4, name
='knn 4, False', rank_weight
=False),
121 cv
= Orange
.evaluation
.testing
.cross_validation(learners
, data
, folds
=5)
123 for l
, score
in zip(learners
, Orange
.evaluation
.scoring
.RMSE(cv
)):
124 print "%s: %.8f" % (l
.name
, score
)
128 this is somewhat inspired by
129 http://quasiphysics.wordpress.com/2011/12/13/visualizing-k-nearest-neighbor-regression/
132 import Image
, ImageDraw
134 attrs
= [ Orange
.feature
.Continuous(name
) for name
in ['X', 'Y', 'color'] ]
137 for num
in xrange(10):
138 color
= 255 * int(2 * random
.random() )
141 return 0.25 + random
.random() / 2
143 x
, y
= get_point(), get_point()
145 insts
.append([x
, y
, color
])
147 data
= Orange
.data
.Table(Orange
.data
.Domain(attrs
), insts
)
150 return Orange
.data
.Instance(Orange
.data
.Domain(data
.domain
.features
),[a
, b
])
152 for k
in xrange(1, 11):
153 for alpha
in xrange(4):
154 for dist
in [Orange
.distance
.Euclidean() ]: #, Orange.distance.Manhattan() ]:
156 l
= KnnWeightedLearner( k
=k
, alpha
=alpha
, distance_constructor
=dist
)
157 #l = Orange.classification.knn.kNNLearner( k=k )
163 for X
in xrange(size
):
164 for Y
in xrange(size
):
165 val
= int(knn(get_inst(float(X
)/size
, float(Y
)/size
)))
168 arr
= numpy
.array(a
, dtype
=numpy
.uint8
)
169 arr
= arr
.reshape((size
, size
))
171 im
= Image
.fromarray(arr
).convert("RGB")
173 y
, x
= int(size
* inst
[0] ), int(size
* inst
[1])
176 draw
= ImageDraw
.Draw(im
)
178 draw
.ellipse((x
-r
, y
-r
, x
+r
, y
+r
), outline
=(255, 0, 0), fill
=(color
, color
, color
))
180 fn
= "knn_w/k=%d_alpha=%d_dist=%s.ppm" % (k
, alpha
, dist
.name
)
185 if __name__
== "__main__":