Changeset 10634:1ebc6f592252 in orange for Orange/classification/svm/__init__.py
 Timestamp:
 03/23/12 20:45:56 (2 years ago)
 Branch:
 default
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

Orange/classification/svm/__init__.py
r10621 r10634 275 275 self.kernel_type = wrapped.kernel_type 276 276 self.__wrapped = wrapped 277 277 278 278 assert(type(wrapped) in [_SVMClassifier, _SVMClassifierSparse]) 279 279 280 280 if self.svm_type in [SVMLearner.C_SVC, SVMLearner.Nu_SVC]: 281 281 # Reorder the support vectors … … 290 290 else: 291 291 self.support_vectors = wrapped.support_vectors 292 292 293 293 @property 294 294 def coef(self): … … 303 303 # for more information on how the coefs are stored by libsvm 304 304 # internally. 305 305 306 306 import numpy as np 307 307 c_map = self._get_libsvm_bin_classifier_map() … … 320 320 nj = label_map[j] 321 321 bc_index, mult = c_map[p] 322 322 323 323 if ni > nj: 324 324 ni, nj = nj, ni 325 325 326 326 # Original class indices 327 327 c1_range = range(libsvm_class_indices[ni], 328 328 libsvm_class_indices[ni + 1]) 329 c2_range = range(libsvm_class_indices[nj], 329 c2_range = range(libsvm_class_indices[nj], 330 330 libsvm_class_indices[nj + 1]) 331 331 332 332 coef1 = mult * coef_array[nj  1, c1_range] 333 333 coef2 = mult * coef_array[ni, c2_range] 334 334 335 335 # Mapped class indices 336 336 c1_range = range(class_indices[i], 337 337 class_indices[i + 1]) 338 c2_range = range(class_indices[j], 338 c2_range = range(class_indices[j], 339 339 class_indices[j + 1]) 340 340 if mult == 1.0: 341 341 c1_range, c2_range = c2_range, c1_range 342 342 343 343 nonzero1 = np.abs(coef1) > 0.0 344 344 nonzero2 = np.abs(coef2) > 0.0 345 345 346 346 coef1 = coef1[nonzero1] 347 347 coef2 = coef2[nonzero2] 348 348 349 349 c1_range = [sv_i for sv_i, nz in zip(c1_range, nonzero1) if nz] 350 350 c2_range = [sv_i for sv_i, nz in zip(c2_range, nonzero2) if nz] 351 351 352 352 coef.append(list(zip(coef1, c1_range)) + list(zip(coef2, c2_range))) 353 353 354 354 p += 1 355 355 return coef 356 356 357 357 @property 358 358 def rho(self): … … 362 362 rho = self.__wrapped.rho 363 363 return [rho[i] * m for i, m in c_map] 364 364 365 365 @property 366 366 def n_SV(self): … … 369 369 if self.__wrapped.n_SV is not None: 370 370 c_map = self._get_libsvm_labels_map() 371 n_SV = self.__wrapped.n_SV371 n_SV = self.__wrapped.n_SV 372 372 return [n_SV[i] for i in c_map] 373 373 else: 374 374 return None 375 375 376 376 @property 377 377 def prob_a(self): … … 383 383 else: 384 384 return None 385 385 386 386 @property 387 387 def prob_b(self): … … 393 393 else: 394 394 return None 395 395 396 396 def __call__(self, instance, what=Orange.core.GetValue): 397 397 """Classify a new ``instance`` … … 417 417 c_map = self._get_libsvm_bin_classifier_map() 418 418 return [dec_values[i] * m for i, m in c_map] 419 419 420 420 def get_model(self): 421 421 """Return a string representing the model in the libsvm model format. 422 422 """ 423 423 return self.__wrapped.get_model() 424 424 425 425 def _get_libsvm_labels_map(self): 426 426 """Get the internal libsvm label mapping. … … 451 451 bin_c_map.append((cls_index, mult)) 452 452 return bin_c_map 453 453 454 454 def __reduce__(self): 455 455 return SVMClassifier, (self.__wrapped,), dict(self.__dict__) 456 456 457 457 def get_binary_classifier(self, c1, c2): 458 458 """Return a binary classifier for classes `c1` and `c2`. … … 461 461 if self.svm_type not in [SVMLearner.C_SVC, SVMLearner.Nu_SVC]: 462 462 raise TypeError("SVM classification model expected.") 463 463 464 464 c1 = int(self.class_var(c1)) 465 465 c2 = int(self.class_var(c2)) 466 466 467 467 n_class = len(self.class_var.values) 468 468 469 469 if c1 == c2: 470 470 raise ValueError("Different classes expected.") 471 471 472 472 bin_class_var = Orange.feature.Discrete("%s vs %s" % \ 473 473 (self.class_var.values[c1], self.class_var.values[c2]), 474 474 values=["0", "1"]) 475 475 476 476 mult = 1.0 477 477 if c1 > c2: 478 478 c1, c2 = c2, c1 479 479 mult = 1.0 480 480 481 481 classifier_i = n_class * (n_class  1) / 2  (n_class  c1  1) * (n_class  c1  2) / 2  (n_class  c2) 482 482 483 483 coef = self.coef[classifier_i] 484 484 485 485 coef1 = [(mult * alpha, sv_i) for alpha, sv_i in coef \ 486 486 if int(self.support_vectors[sv_i].get_class()) == c1] 487 487 coef2 = [(mult * alpha, sv_i) for alpha, sv_i in coef \ 488 if int(self.support_vectors[sv_i].get_class()) == c2] 489 488 if int(self.support_vectors[sv_i].get_class()) == c2] 489 490 490 rho = mult * self.rho[classifier_i] 491 492 model = self._binary_libsvm_model_string(bin_class_var, 491 492 model = self._binary_libsvm_model_string(bin_class_var, 493 493 [coef1, coef2], 494 494 [rho]) 495 495 496 496 all_sv = [self.support_vectors[sv_i] \ 497 for c, sv_i in coef1 + coef2] 498 497 for c, sv_i in coef1 + coef2] 498 499 499 all_sv = Orange.data.Table(all_sv) 500 500 501 501 svm_classifier_type = type(self.__wrapped) 502 502 503 503 # Build args for svm_classifier_type constructor 504 504 args = (bin_class_var, self.examples, all_sv, model) 505 505 506 506 if isinstance(svm_classifier_type, _SVMClassifierSparse): 507 507 args = args + (int(self.__wrapped.use_non_meta),) 508 508 509 509 if self.kernel_type == kernels.Custom: 510 510 args = args + (self.kernel_func,) 511 511 512 512 native_classifier = svm_classifier_type(*args) 513 513 return SVMClassifier(native_classifier) 514 514 515 515 def _binary_libsvm_model_string(self, class_var, coef, rho): 516 516 """Return a libsvm formated model string for binary classifier 517 517 """ 518 518 import itertools 519 519 520 520 model = [] 521 521 522 522 # Take the model up to nr_classes 523 523 libsvm_model = self.__wrapped.get_model() … … 527 527 else: 528 528 model.append(line.rstrip()) 529 529 530 530 model.append("nr_class %i" % len(class_var.values)) 531 531 model.append("total_sv %i" % reduce(add, [len(c) for c in coef])) … … 533 533 model.append("label " + " ".join(str(i) for i in range(len(class_var.values)))) 534 534 # No probA and probB 535 535 536 536 model.append("nr_sv " + " ".join(str(len(c)) for c in coef)) 537 537 model.append("SV") 538 538 539 539 def instance_to_svm(inst): 540 540 values = [(i, float(inst[v])) \ … … 542 542 if not inst[v].is_special() and float(inst[v]) != 0.0] 543 543 return " ".join("%i:%f" % (i + 1, v) for i, v in values) 544 544 545 545 def sparse_instance_to_svm(inst): 546 546 non_meta = [] … … 554 554 metas.append("%i:%f" % (base  m_id, float(value))) 555 555 return " ".join(non_meta + metas) 556 556 557 557 if isinstance(self.__wrapped, _SVMClassifierSparse): 558 558 converter = sparse_instance_to_svm 559 559 else: 560 560 converter = instance_to_svm 561 561 562 562 if self.kernel_type == kernels.Custom: 563 563 SV = libsvm_model.split("SV\n", 1)[1] 564 564 # Get the sv indices (the last entry in the SV lines) 565 565 indices = [int(s.split(":")[1]) for s in SV.splitlines() if s.strip()] 566 566 567 567 # Reorder the indices 568 568 label_map = self._get_libsvm_labels_map() … … 574 574 reordered_indices = [reordered_indices[i] for i in label_map] 575 575 indices = reduce(add, reordered_indices) 576 576 577 577 for (c, sv_i) in itertools.chain(*coef): 578 578 model.append("%f 0:%i" % (c, indices[sv_i])) … … 580 580 for (c, sv_i) in itertools.chain(*coef): 581 581 model.append("%f %s" % (c, converter(self.support_vectors[sv_i]))) 582 582 583 583 model.append("") 584 584 return "\n".join(model) 585 585 586 586 587 587 SVMClassifier = Orange.utils.deprecated_members({ … … 590 590 "getModel" : "get_model", 591 591 }, wrap_methods=[])(SVMClassifier) 592 592 593 593 # Backwards compatibility (pickling) 594 594 SVMClassifierWrapper = SVMClassifier … … 659 659 parameters.append(("gamma", [2 ** a for a in range(5, 5, 2)] + [0])) 660 660 import orngWrap 661 tunedLearner = orngWrap.TuneMParameters( object=self.learner,661 tunedLearner = orngWrap.TuneMParameters(learner=self.learner, 662 662 parameters=parameters, 663 663 folds=self.folds) 664 664 665 return tunedLearner(newexamples, verbose=self.verbose)665 return tunedLearner(newexamples, verbose=self.verbose) 666 666 667 667 class SVMLearnerSparseEasy(SVMLearnerEasy): … … 777 777 if classifier.svm_type not in [SVMLearner.C_SVC, SVMLearner.Nu_SVC]: 778 778 raise TypeError("SVM classification model expected.") 779 779 780 780 classes = classifier.class_var.values 781 781 782 782 for i in range(len(classes)  1): 783 783 for j in range(i + 1, len(classes)): … … 789 789 SVs = bin_classifier.support_vectors 790 790 w = {} 791 791 792 792 for alpha, sv_ind in bin_classifier.coef[0]: 793 793 SV = SVs[sv_ind] … … 797 797 if attr.varType == Orange.feature.Type.Continuous: 798 798 update_weights(w, attr, to_float(SV[attr]), alpha) 799 799 800 800 weights.append(w) 801 801 802 802 if sum: 803 803 scores = defaultdict(float)
Note: See TracChangeset
for help on using the changeset viewer.