Ejemplo n.º 1
0
class TestSVM(unittest.TestCase):
    def setUp(self) -> None:
        physical_devices = tf.config.list_physical_devices('GPU')
        if physical_devices is not None and len(physical_devices) > 0:
            tf.config.experimental.set_memory_growth(physical_devices[0], True)
        self.data_loader = DataLoader()

    def gen_dataset(self, x, y, batch_size):
        x, y = tf.cast(x,
                       dtype=tf.float32), tf.reshape(tf.cast(y,
                                                             dtype=tf.float32),
                                                     shape=(-1, 1))
        return tf.data.Dataset.from_tensor_slices(
            (x, y)).batch(batch_size, drop_remainder=True)

    def test_linear(self):
        (x_train, y_train), (x_test, y_test) = self.data_loader.loadIris1(0.8)
        svm = LinearSVM(num_feature=2)
        svm.compile(optimizer=tf.optimizers.SGD(0.01),
                    loss=svm.loss,
                    metrics=[svm.accu])
        svm.fit(x_train, y_train, batch_size=64, epochs=400, verbose=0)

        results = svm.evaluate(x_test, y_test)
        print("test result: ", results, svm.params())

        self.assertGreater(results[1], 0.9)

        a = float(-svm.W[0] / svm.W[1])
        xx = np.linspace(-2.5, 2.5)
        yy = a * xx - float(svm.b / svm.W[1])

        self.data_loader.plot1(
            (0.0, 10.0),
            (float(-svm.b.numpy() / svm.W.numpy()[1]),
             float(
                 (-svm.b.numpy() - 10 * svm.W.numpy()[0]) / svm.W.numpy()[1])),
            color='black').show()

    def test_gaussian(self):
        def draw(x_vals, y_vals, show=True):
            class1_x = [x[0] for i, x in enumerate(x_vals) if y_vals[i] == 1]
            class1_y = [x[1] for i, x in enumerate(x_vals) if y_vals[i] == 1]
            class2_x = [x[0] for i, x in enumerate(x_vals) if y_vals[i] == -1]
            class2_y = [x[1] for i, x in enumerate(x_vals) if y_vals[i] == -1]
            if show:
                plt.plot(class1_x, class1_y, 'ro', label='I. setosa')
                plt.plot(class2_x, class2_y, 'kx', label='I. versicolor')
                # plt.plot(class3_x, class3_y, 'gv', label='I. virginica')
                plt.title('Gaussian SVM Results on Iris Data')
                plt.xlabel('Pedal Length')
                plt.ylabel('Sepal Width')
                plt.legend(loc='lower right')
                plt.show()
            return class1_x, class1_y, class2_x, class2_y

        (x_vals, y_vals) = sklearn.datasets.make_circles(n_samples=3000,
                                                         factor=.5,
                                                         noise=.1)
        y_vals = np.array([1.0 if y == 1.0 else -1.0 for y in y_vals],
                          dtype=np.float)

        split_ratio = 0.9
        x_train, y_train = x_vals[0:int(len(x_vals) * split_ratio)], y_vals[
            0:int(len(y_vals) * split_ratio)]
        x_test, y_test = x_vals[int(len(x_vals) * split_ratio
                                    ):], y_vals[int(len(y_vals) *
                                                    split_ratio):]
        draw(x_train, y_train)
        draw(x_test, y_test)

        batch_size = 256
        epochs = 300
        svm = GaussianKernelSVM(batch_size=batch_size)
        optimizer = tf.keras.optimizers.SGD(0.001)
        train_dataset = self.gen_dataset(x_train, y_train, batch_size)
        test_dataset = self.gen_dataset(x_test, y_test, 5)

        # train
        def train_step(x_sample, y_sample):
            with tf.GradientTape() as tape:
                pred_kernel = svm(x_sample, x_sample)
                loss = svm.loss(y_sample, pred_kernel)
                accu, _ = svm.accu(y_sample, y_sample, pred_kernel)
            gradients = tape.gradient(
                loss, svm.trainable_variables)  # had to indent this!
            optimizer.apply_gradients(zip(gradients, svm.trainable_variables))
            return loss, accu

        for epoch in range(epochs):
            accus, losses = [], []
            for (batch, (x, y)) in enumerate(train_dataset):
                loss, accu = train_step(x_sample=x, y_sample=y)
                accus.append(accu.numpy())
                losses.append(loss.numpy())
            print("Epoch: {}, accu: {}, loss: {}".format(
                epoch, np.mean(accus), np.mean(losses)))

        # test
        rand_index = np.random.choice(len(x_vals), size=batch_size)
        rand_x = x_vals[rand_index]
        rand_y = tf.convert_to_tensor(np.transpose([y_vals[rand_index]]),
                                      dtype=tf.float32)
        accus = []
        for (batch, (x, y)) in enumerate(test_dataset):
            pred_kernel = svm(x, rand_x)
            accu, _ = svm.accu(y, rand_y, pred_kernel)
            accus.append(accu)
        print("test accuracy: {}".format(np.mean(accus)))
        self.assertGreater(np.mean(accus), 0.8)
        # plot results
        x_min, x_max = x_vals[:, 0].min() - 1, x_vals[:, 0].max() + 1
        y_min, y_max = x_vals[:, 1].min() - 1, x_vals[:, 1].max() + 1
        xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                             np.arange(y_min, y_max, 0.02))
        grid_points = np.c_[xx.ravel(), yy.ravel()]
        output_kernel = svm(grid_points, rand_x)
        _, predictions = svm.accu(None, rand_y, output_kernel)
        grid_predictions = tf.reshape(predictions, xx.shape)

        # Plot points and grid
        class1_x, class1_y, class2_x, class2_y = draw(x_vals, y_vals, False)
        plt.contourf(xx, yy, grid_predictions, cmap=plt.cm.Paired, alpha=0.8)
        plt.plot(class1_x, class1_y, 'ro', label='Class 1')
        plt.plot(class2_x, class2_y, 'kx', label='Class -1')
        plt.title('Gaussian SVM Results')
        plt.xlabel('x')
        plt.ylabel('y')
        plt.legend(loc='lower right')
        plt.ylim([-1.5, 1.5])
        plt.xlim([-1.5, 1.5])
        plt.show()

    def test_amsvm(self):
        (x_train, y_train) = self.data_loader.loadIris2(0.8)
        svm = AMSVM(num_classes=3, num_feature=2, c=0.001)
        # optimizer = tf.keras.optimizers.Adam(0.1)
        # train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(50, drop_remainder=True).shuffle(
        #     50)
        # train
        # def train_step(x_sample, y_sample):
        #     with tf.GradientTape() as tape:
        #         output = svm(x_sample)
        #         loss = svm.loss(y_sample, output)
        #         accu = svm.accu(y_sample, output)
        #     gradients = tape.gradient(loss, svm.trainable_variables)  # had to indent this!
        #     optimizer.apply_gradients(zip(gradients, svm.trainable_variables))
        #     return loss, accu
        #
        # for epoch in range(400):
        #     accus, losses = [], []
        #     for (batch, (x, y)) in enumerate(train_dataset):
        #         loss, accu = train_step(x_sample=x, y_sample=y)
        #         accus.append(accu.numpy())
        #         losses.append(loss.numpy())
        #     print("Epoch: {}, accu: {}, loss: {}".format(epoch, np.mean(accus), np.mean(losses)))

        svm.compile(optimizer=tf.optimizers.Adam(0.1),
                    loss=svm.loss,
                    metrics=[svm.accu])
        svm.fit(x_train, y_train, batch_size=50, epochs=100)
Ejemplo n.º 2
0
# -*- coding: utf-8 -*-
"""
@Ref: https://www.cvxpy.org/examples/machine_learning/svm.html
@Author: xiezizhe
@Date: 17/2/2020 下午2:45
"""
import cvxpy as cp
from utils.DataLoader import DataLoader
import numpy as np

if __name__ == "__main__":
    data_loader = DataLoader()
    (x_train, y_train), (x_test, y_test) = data_loader.loadIris1(0.8)

    n = 2
    m = len(x_train)

    W = cp.Variable((n, 1))
    b = cp.Variable()
    loss = cp.sum(
        cp.pos(1 - cp.multiply(np.reshape(y_train.numpy(), (m, 1)),
                               x_train.numpy() @ W + b)))
    reg = cp.norm(W, 1)
    lambd = cp.Parameter(nonneg=True)
    prob = cp.Problem(cp.Minimize(loss / m + lambd * reg))
    lambd.value = 0.1
    prob.solve()

    print("{} * w + {}".format(W.value, b.value))
    data_loader.plot1((0.0, 10.0), (float(
        -b.value / W.value[1]), float(