From b90d36ebe9094722e6fb647995d8bf47da8075ea Mon Sep 17 00:00:00 2001 From: Peter Prettenhofer <peter.prettenhofer@gmail.com> Date: Thu, 18 Nov 2010 19:28:45 +0800 Subject: [PATCH] added tksvm from git://gist.github.com/673953.git. --- examples/svm/svm_gui.py | 283 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 examples/svm/svm_gui.py diff --git a/examples/svm/svm_gui.py b/examples/svm/svm_gui.py new file mode 100644 index 0000000000..ebc9299363 --- /dev/null +++ b/examples/svm/svm_gui.py @@ -0,0 +1,283 @@ +""" +========== +Libsvm GUI +========== + +A simple graphical frontend for Libsvm mainly intended for didactic +purposes. You can create data points by point and click and visualize +the decision region induced by different kernels and parameter settings. + +To create positive examples click the left mouse button; to create +negative examples click the right button. + +If all examples are from the same class, it uses a one-class svm. + +Requirements +------------ + + - Tkinter + - scikits.learn + - matplotlib with TkAgg + +""" +from __future__ import division + +print __doc__ + +#!/usr/bin/env python +# +# Author: Peter Prettenhoer <peter.prettenhofer@gmail.com> +# +# License: BSD Style. + +import matplotlib +matplotlib.use('TkAgg') + +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg +from matplotlib.figure import Figure + +import Tkinter as Tk +import sys +import numpy as np + +from scikits.learn import svm + +y_min, y_max = -50, 50 +x_min, x_max = -50, 50 + + +class Model(object): + def __init__(self): + self.observers = [] + self.surface = None + self.data = [] + self.cls = None + self.surface_type = 0 + + def changed(self, event): + for observer in self.observers: + observer.update(event, self) + + def add_observer(self, observer): + self.observers.append(observer) + + def set_surface(self, surface): + self.surface = surface + + +class Controller(object): + def __init__(self, model): + self.model = model + self.kernel = Tk.IntVar() + self.surface_type = Tk.IntVar() + + def classify(self): + print "classifying data" + train = np.array(self.model.data) + X = train[:, :2] + y = train[:, 2] + + C = float(self.complexity.get()) + gamma = float(self.gamma.get()) + coef0 = float(self.coef0.get()) + degree = int(self.degree.get()) + kernel_map = {0: "linear", 1: "rbf", 2: "poly"} + if len(np.unique(y)) == 1: + clf = svm.OneClassSVM(kernel=kernel_map[self.kernel.get()], + C=C, gamma=gamma, coef0=coef0, degree=degree) + clf.fit(X) + else: + clf = svm.SVC(kernel=kernel_map[self.kernel.get()], C=C, + gamma=gamma, coef0=coef0, degree=degree) + clf.fit(X, y) + if hasattr(clf, 'score'): + print "Accuracy:", clf.score(X, y) * 100 + X1, X2, Z = self.decision_surface(clf) + self.model.clf = clf + self.model.set_surface((X1, X2, Z)) + self.model.surface_type = self.surface_type.get() + self.model.changed("surface") + + def decision_surface(self, cls): + delta = 1 + x = np.arange(x_min, x_max + delta, delta) + y = np.arange(y_min, y_max + delta, delta) + X1, X2 = np.meshgrid(x, y) + Z = cls.predict_margin(np.c_[X1.ravel(), X2.ravel()]) + Z = Z.reshape(X1.shape) + return X1, X2, Z + + def clear_data(self): + self.model.data = [] + self.model.changed("clear") + + def add_example(self, x, y, label): + self.model.data.append((x, y, label)) + self.model.changed("example_added") + + +class View(object): + def __init__(self, root, controller): + f = Figure() + ax = f.add_subplot(111) + ax.set_xticks([]) + ax.set_yticks([]) + ax.set_xlim((x_min, x_max)) + ax.set_ylim((y_min, y_max)) + canvas = FigureCanvasTkAgg(f, master=root) + canvas.show() + canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) + canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) + canvas.mpl_connect('button_press_event', self.onclick) + toolbar = NavigationToolbar2TkAgg(canvas, root) + toolbar.update() + self.controllbar = ControllBar(root, controller) + self.f = f + self.ax = ax + self.canvas = canvas + self.controller = controller + self.hascolormaps = False + self.contours = [] + self.c_labels = None + self.plot_kernels() + + def plot_kernels(self): + self.ax.text(-50, -60, "Linear: $u^T v$") + self.ax.text(-20, -60, "RBF: $\exp (-\gamma \| u-v \|^2)$") + self.ax.text(10, -60, "Poly: $(\gamma \, u^T v + r)^d$") + + def onclick(self, event): + if event.xdata and event.ydata: + if event.button == 1: + self.controller.add_example(event.xdata, event.ydata, 1) + elif event.button == 3: + self.controller.add_example(event.xdata, event.ydata, -1) + + def update(self, event, model): + #print "update. msg:%s" % event + if event == "example_added": + x, y, l = model.data[-1] + if l == 1: + color = 'w' + elif l == -1: + color = 'k' + self.ax.plot([x], [y], "%so" % color, scalex=0.0, scaley=0.0) + + if event == "clear": + self.ax.clear() + self.ax.set_xticks([]) + self.ax.set_yticks([]) + self.contours = [] + self.c_labels = None + self.plot_kernels() + + if event == "surface": + self.plot_decision_surface(model.surface, model.surface_type) + + self.canvas.draw() + + def plot_decision_surface(self, surface, type): + X1, X2, Z = surface + + if len(self.contours) > 0: + for contour in self.contours: + for lineset in contour.collections: + lineset.remove() + self.contours = [] + + if self.c_labels: + for label in self.c_labels: + label.remove() + + if type == 0: + levels = [-1.0, 0.0, 1.0] + linestyles = ['dashed', 'solid', 'dashed'] + colors = 'k' + self.contours.append(self.ax.contour(X1, X2, Z, levels, + colors=colors, + linestyles=linestyles)) + elif type == 1: + self.contours.append(self.ax.contourf(X1, X2, Z, 10, + cmap=matplotlib.cm.bone, + origin='lower', + alpha=0.85)) + self.contours.append(self.ax.contour(X1, X2, Z, [0.0], + colors='k', + linestyles=['solid'])) + else: + raise ValueError("surface type unknown") + + +class ControllBar: + def __init__(self, root, controller): + fm = Tk.Frame(root) + kernel_group = Tk.Frame(fm) + Tk.Radiobutton(kernel_group, text="Linear", variable=controller.kernel, + value=0).pack(anchor=Tk.W) + Tk.Radiobutton(kernel_group, text="RBF", variable=controller.kernel, + value=1).pack(anchor=Tk.W) + Tk.Radiobutton(kernel_group, text="Poly", variable=controller.kernel, + value=2).pack(anchor=Tk.W) + kernel_group.pack(side=Tk.LEFT) + + valbox = Tk.Frame(fm) + controller.complexity = Tk.StringVar() + controller.complexity.set("1.0") + c = Tk.Frame(valbox) + Tk.Label(c, text="C:", anchor="e", width=7).pack(side=Tk.LEFT) + Tk.Entry(c, width=6, textvariable=controller.complexity).pack( + side=Tk.LEFT) + c.pack() + + controller.gamma = Tk.StringVar() + controller.gamma.set("0.01") + g = Tk.Frame(valbox) + Tk.Label(g, text="gamma:", anchor="e", width=7).pack(side=Tk.LEFT) + Tk.Entry(g, width=6, textvariable=controller.gamma).pack(side=Tk.LEFT) + g.pack() + + controller.degree = Tk.StringVar() + controller.degree.set("3") + d = Tk.Frame(valbox) + Tk.Label(d, text="degree:", anchor="e", width=7).pack(side=Tk.LEFT) + Tk.Entry(d, width=6, textvariable=controller.degree).pack(side=Tk.LEFT) + d.pack() + + controller.coef0 = Tk.StringVar() + controller.coef0.set("0") + r = Tk.Frame(valbox) + Tk.Label(r, text="coef0:", anchor="e", width=7).pack(side=Tk.LEFT) + Tk.Entry(r, width=6, textvariable=controller.coef0).pack( + side=Tk.LEFT) + r.pack() + valbox.pack(side=Tk.LEFT) + + cmap_group = Tk.Frame(fm) + Tk.Radiobutton(cmap_group, text="Hyperplanes", + variable=controller.surface_type, value=0).pack( + anchor=Tk.W) + Tk.Radiobutton(cmap_group, text="Surface", + variable=controller.surface_type, value=1).pack( + anchor=Tk.W) + + cmap_group.pack(side=Tk.LEFT) + + train_button = Tk.Button(fm, text='Train', command=controller.classify) + train_button.pack() + fm.pack(side=Tk.LEFT) + Tk.Button(fm, text='Clear', + command=controller.clear_data).pack(side=Tk.LEFT) + + +def main(argv): + root = Tk.Tk() + model = Model() + controller = Controller(model) + root.wm_title("SVM") + view = View(root, controller) + model.add_observer(view) + Tk.mainloop() + +if __name__ == "__main__": + main(sys.argv) -- GitLab