Changeset 10637:13a1ab18e5cf in orange for Orange/classification/svm/__init__.py
 Timestamp:
 03/26/12 12:11:11 (2 years ago)
 Branch:
 default
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

Orange/classification/svm/__init__.py
r10621 r10637 293 293 @property 294 294 def coef(self): 295 """Coefficients of the underlying binary 1vs1 classifiers. 296 297 This is a #Classes * (#Classses  1) list of lists where 298 each sublist contains tuples of (alpha, support_vector_index) 295 """Coefficients of the underlying svm model. 296 297 If this is a classification model then this is a list of 298 coefficients for each binary 1vs1 classifiers, i.e. 299 #Classes * (#Classses  1) list of lists where 300 each sublist contains tuples of (coef, support_vector_index) 301 302 For regression models it is still a list of lists (for consistency) 303 but of length 1 e.g. [[(coef, support_vector_index), ... ]] 299 304 300 305 """ 301 # We need to reorder the coef values 302 # see http://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html#f804 303 # for more information on how the coefs are stored by libsvm 304 # internally. 305 306 import numpy as np 307 c_map = self._get_libsvm_bin_classifier_map() 308 label_map = self._get_libsvm_labels_map() 309 libsvm_coef = self.__wrapped.coef 310 coef = [] #[None] * len(c_map) 311 n_class = len(label_map) 312 n_SV = self.__wrapped.n_SV 313 coef_array = np.array(self.__wrapped.coef) 314 p = 0 315 libsvm_class_indices = np.cumsum([0] + list(n_SV), dtype=int) 316 class_indices = np.cumsum([0] + list(self.n_SV), dtype=int) 317 for i in range(n_class  1): 318 for j in range(i + 1, n_class): 319 ni = label_map[i] 320 nj = label_map[j] 321 bc_index, mult = c_map[p] 322 323 if ni > nj: 324 ni, nj = nj, ni 325 326 # Original class indices 327 c1_range = range(libsvm_class_indices[ni], 328 libsvm_class_indices[ni + 1]) 329 c2_range = range(libsvm_class_indices[nj], 330 libsvm_class_indices[nj + 1]) 331 332 coef1 = mult * coef_array[nj  1, c1_range] 333 coef2 = mult * coef_array[ni, c2_range] 334 335 # Mapped class indices 336 c1_range = range(class_indices[i], 337 class_indices[i + 1]) 338 c2_range = range(class_indices[j], 339 class_indices[j + 1]) 340 if mult == 1.0: 341 c1_range, c2_range = c2_range, c1_range 306 if isinstance(self.class_var, variable.Discrete): 307 # We need to reorder the coef values 308 # see http://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html#f804 309 # for more information on how the coefs are stored by libsvm 310 # internally. 311 import numpy as np 312 c_map = self._get_libsvm_bin_classifier_map() 313 label_map = self._get_libsvm_labels_map() 314 libsvm_coef = self.__wrapped.coef 315 coef = [] #[None] * len(c_map) 316 n_class = len(label_map) 317 n_SV = self.__wrapped.n_SV 318 coef_array = np.array(self.__wrapped.coef) 319 p = 0 320 libsvm_class_indices = np.cumsum([0] + list(n_SV), dtype=int) 321 class_indices = np.cumsum([0] + list(self.n_SV), dtype=int) 322 for i in range(n_class  1): 323 for j in range(i + 1, n_class): 324 ni = label_map[i] 325 nj = label_map[j] 326 bc_index, mult = c_map[p] 342 327 343 nonzero1 = np.abs(coef1) > 0.0 344 nonzero2 = np.abs(coef2) > 0.0 345 346 coef1 = coef1[nonzero1] 347 coef2 = coef2[nonzero2] 348 349 c1_range = [sv_i for sv_i, nz in zip(c1_range, nonzero1) if nz] 350 c2_range = [sv_i for sv_i, nz in zip(c2_range, nonzero2) if nz] 351 352 coef.append(list(zip(coef1, c1_range)) + list(zip(coef2, c2_range))) 353 354 p += 1 328 if ni > nj: 329 ni, nj = nj, ni 330 331 # Original class indices 332 c1_range = range(libsvm_class_indices[ni], 333 libsvm_class_indices[ni + 1]) 334 c2_range = range(libsvm_class_indices[nj], 335 libsvm_class_indices[nj + 1]) 336 337 coef1 = mult * coef_array[nj  1, c1_range] 338 coef2 = mult * coef_array[ni, c2_range] 339 340 # Mapped class indices 341 c1_range = range(class_indices[i], 342 class_indices[i + 1]) 343 c2_range = range(class_indices[j], 344 class_indices[j + 1]) 345 if mult == 1.0: 346 c1_range, c2_range = c2_range, c1_range 347 348 nonzero1 = np.abs(coef1) > 0.0 349 nonzero2 = np.abs(coef2) > 0.0 350 351 coef1 = coef1[nonzero1] 352 coef2 = coef2[nonzero2] 353 354 c1_range = [sv_i for sv_i, nz in zip(c1_range, nonzero1) if nz] 355 c2_range = [sv_i for sv_i, nz in zip(c2_range, nonzero2) if nz] 356 357 coef.append(list(zip(coef1, c1_range)) + list(zip(coef2, c2_range))) 358 359 p += 1 360 else: 361 coef = [zip(self.__wrapped.coef[0], range(len(self.support_vectors)))] 362 355 363 return coef 356 364 357 365 @property 358 366 def rho(self): 359 """Constant (bias) terms in each underlying binary 1vs1 classifier. 360 """ 361 c_map = self._get_libsvm_bin_classifier_map() 367 """Constant (bias) terms of the svm model. 368 369 For classification models this is a list of bias terms 370 for each binary 1vs1 classifier. 371 372 For regression models it is a list with a single value. 373 374 """ 362 375 rho = self.__wrapped.rho 363 return [rho[i] * m for i, m in c_map] 376 if isinstance(self.class_var, variable.Discrete): 377 c_map = self._get_libsvm_bin_classifier_map() 378 return [rho[i] * m for i, m in c_map] 379 else: 380 return list(rho) 364 381 365 382 @property 366 383 def n_SV(self): 367 384 """Number of support vectors for each class. 385 For regression models this is `None`. 386 368 387 """ 369 388 if self.__wrapped.n_SV is not None: … … 374 393 return None 375 394 395 # Pairwise probability is expresed as: 396 # 1.0 / (1.0 + exp(dec_val[i] * prob_a[i] + prob_b[i])) 397 # Since dec_val already changes signs if we switch the 398 # classifier direction only prob_b must change signs 376 399 @property 377 400 def prob_a(self): 378 401 if self.__wrapped.prob_a is not None: 379 c_map = self._get_libsvm_bin_classifier_map() 380 prob_a = self.__wrapped.prob_a 381 # TODO: What about order switch? 382 return [prob_a[i] for i, _ in c_map] 402 if isinstance(self.class_var, variable.Discrete): 403 c_map = self._get_libsvm_bin_classifier_map() 404 prob_a = self.__wrapped.prob_a 405 return [prob_a[i] for i, _ in c_map] 406 else: 407 # A single value for regression 408 return list(self.__wrapped.prob_a) 383 409 else: 384 410 return None … … 389 415 c_map = self._get_libsvm_bin_classifier_map() 390 416 prob_b = self.__wrapped.prob_b 391 # TODO: What about order switch?392 return [prob_b[i] for i, _in c_map]417 # Change sign when changing the classifier direction 418 return [prob_b[i] * m for i, m in c_map] 393 419 else: 394 420 return None … … 413 439 instance = Orange.data.Instance(self.domain, instance) 414 440 dec_values = self.__wrapped.get_decision_values(instance) 415 # decision values are ordered by libsvm internal class values 416 # i.e. the order of labels in the data 417 c_map = self._get_libsvm_bin_classifier_map() 418 return [dec_values[i] * m for i, m in c_map] 441 if isinstance(self.class_var, variable.Discrete): 442 # decision values are ordered by libsvm internal class values 443 # i.e. the order of labels in the data 444 c_map = self._get_libsvm_bin_classifier_map() 445 return [dec_values[i] * m for i, m in c_map] 446 else: 447 return list(dec_values) 419 448 420 449 def get_model(self): … … 433 462 434 463 def _get_libsvm_bin_classifier_map(self): 435 """Return the libsvm binary classifier mapping (due to label ordering) 436 """ 464 """Return the libsvm binary classifier mapping (due to label ordering). 465 """ 466 if not isinstance(self.class_var, variable.Discrete): 467 raise TypeError("SVM classification model expected") 437 468 label_map = self._get_libsvm_labels_map() 438 469 bin_c_map = [] … … 518 549 import itertools 519 550 551 if not isinstance(self.class_var, variable.Discrete): 552 raise TypeError("SVM classification model expected") 553 520 554 model = [] 521 555 522 556 # Take the model up to nr_classes 523 557 libsvm_model = self.__wrapped.get_model()
Note: See TracChangeset
for help on using the changeset viewer.