示例#1
0
    def test_model(name, model):
        correct = 0
        total = 0
        converted_class_labels, class_images = convert_labels(
            test_labels, test_images, name)

        if name == "binary":
            for i in range(len(converted_class_labels)):
                if converted_class_labels[i] != int(
                        test_labels[i] in animal_labels):
                    print(
                        "Error in conversion for binary classification - exiting"
                    )
                    exit()
        class_logits = model.predict(class_images)

        if name != "binary":
            class_preds = np.argmax(tf.nn.softmax(class_logits), axis=1)
        else:
            # print(class_logits, class_logits.shape)
            class_preds = tf.round(tf.nn.sigmoid(class_logits))
        class_preds = tf.reshape(class_preds, [len(class_preds)])
        # class_preds = np.argmax(class_preds, axis=1)
        for i in range(len(class_images)):
            prediction = int(class_preds[i])
            total += 1
            if prediction == converted_class_labels[i]:
                correct += 1
        print(name +
              " reported accuracy: {:5.2f}%".format(100 * correct / total))
        loss, acc = model.evaluate(class_images,
                                   converted_class_labels,
                                   verbose=2)
        print(name + " true accuracy: {:5.2f}%".format(100 * acc))
    def test_model(name, model):
        correct = 0
        total = 0
        converted_class_labels, class_images = convert_labels(test_labels, test_images, name)


        class_logits = model.predict(class_images)

        class_preds = np.argmax(tf.nn.softmax(class_logits), axis=1)
        # class_preds = tf.round(tf.nn.sigmoid(class_logits))
        class_preds = tf.reshape(class_preds, [len(class_preds)])
        for i in range(len(class_images)):
            prediction = int(class_preds[i])
            total += 1
            if prediction == converted_class_labels[i]:
                correct += 1
        print(name + " reported accuracy: {:5.2f}%".format(100 * correct / total))
        loss, acc = model.evaluate(class_images, converted_class_labels, verbose=2)
        print(name + " true accuracy: {:5.2f}%".format(100 * acc))
def main(argv):

    opts, args = getopt.getopt(argv, "hi:o:", ["test=", "experiment=", "subset=", "self_train=", "epochs=", "batch=", "threshold="])

    self_train = False
    subset_size = 1
    epochs = 15
    batch_size = 1000
    threshold = .75
    experiment = "default"
    binary_classification = False

    for opt, arg in opts:
        if opt == '-h':
            print('self-train.py --experiment=binary --subset=1 --self_train=True --epochs=20 --batch=1000 --threshold=.75')
            sys.exit()
        elif opt in ("-st", "--self_train"):
            self_train= arg.lower() in ["true", "True"]
        elif opt in ("-ss", "--subset"):
            subset_size = float(arg)
        elif opt in ("-exp", "--experiment"):
            experiment = arg
            if experiment=="binary":
                binary_classification = True
        elif opt in ("-e", "--epochs"):
            epochs = int(arg)
        elif opt in ("-b", "--batch"):
            batch_size = int(arg)
        elif opt in ("-t", "--threshold"):
            threshold = float(arg)

    print("self-train: ", self_train)
    IMG_HEIGHT = 96
    IMG_WIDTH = 96

    binary_path = "data/stl10_binary/"

    # if experiment != "disagreement":

    og_train_images = read_all_images(binary_path + "train_X.bin")
    og_train_labels = read_labels(binary_path + "train_y.bin")

    og_test_images = read_all_images(binary_path + "test_X.bin")
    og_test_labels = read_labels(binary_path + "test_y.bin")

    experiments = []
    if experiment == "disagreement":
        experiments = ["disagreement_animal", "disagreement_machine"]
    else:
        experiments = [experiment]

    models = []
    all_train_labels = []
    all_test_labels = []
    histories = []

    for sub_experiment in experiments:

        checkpoint_path = "training/" + sub_experiment + "-cp-{epoch:04d}.ckpt"
        checkpoint_dir = os.path.dirname(checkpoint_path)

        # Create a callback that saves the model's weights every 5 epochs
        cp_callback = tf.keras.callbacks.ModelCheckpoint(
            filepath=checkpoint_path,
            verbose=1,
            save_weights_only=True,
            period=5)

        test_labels, test_images = convert_labels(og_test_labels, og_test_images, sub_experiment)
        train_labels, train_images = convert_labels(og_train_labels, og_train_images, sub_experiment)

        num_train = math.floor(len(train_labels)*subset_size)
        num_test = math.floor(len(test_labels)*subset_size)

        test_labels = test_labels[:num_test]
        train_labels = train_labels[:num_train]
        test_images = test_images[:num_test]
        train_images = train_images[:num_train]
        all_train_labels.append(train_labels)
        all_test_labels.append(test_labels)

        print(num_train, batch_size)

        num_batches = math.ceil(num_train/batch_size)
        batch_size = int(num_train/num_batches)

        print("Adjusted batch size to " + str(batch_size))

        if sub_experiment == "binary":
            num_classes = 1
        elif sub_experiment == "animal":
            num_classes = 6
        elif sub_experiment == "machine":
            num_classes = 4
        elif sub_experiment == "disagreement_animal":
            num_classes = 7
        elif sub_experiment == "disagreement_machine":
            num_classes = 5
        else:
            num_classes = 10


        # model = Sequential([
        #     Conv2D(16, 3, padding='same', activation='relu',
        #            input_shape=(IMG_HEIGHT, IMG_WIDTH ,3),
        #            kernel_regularizer=regularizers.l2(0.01),
        #            bias_regularizer = regularizers.l2(0.01),
        #            activity_regularizer = regularizers.l2(0.01)),
        #     MaxPooling2D(),
        #     Dropout(0.2),
        #     Conv2D(32, 3, padding='same', activation='relu'),
        #     MaxPooling2D(),
        #     Conv2D(64, 3, padding='same', activation='relu'),
        #     MaxPooling2D(),
        #     Dropout(0.2),
        #     Flatten(),
        #     Dense(512, activation='relu'),
        #     Dense(num_classes)
        # ])
        base_model = ResNet50(weights = None,
                         include_top = False,
                         input_shape = (IMG_HEIGHT, IMG_WIDTH, 3))

        # Next 4 lines copied from:
        #https://github.com/priya-dwivedi/Deep-Learning/blob/master/resnet_keras/Residual_Network_Keras.ipynb
        x = base_model.output
        x = GlobalAveragePooling2D()(x)
        x = Dropout(0.2)(x)
        predictions = Dense(num_classes, activation= 'softmax')(x)
        model = Model(inputs = base_model.input, outputs = predictions)

        if experiment=="binary":
            model.compile(optimizer='adam',
                          loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
                          metrics=['accuracy'])
        else:
            model.compile(optimizer = Adam(lr = 0.0001),
                          loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                          metrics=['accuracy'])

        model.summary()

        aug = ImageDataGenerator(
            rotation_range=30,
            zoom_range=0.15,
            width_shift_range=0.2,
            height_shift_range=0.2,
            shear_range=0.15,
            horizontal_flip=True,
            fill_mode="nearest")

        histories.append(model.fit(
            # fixed
            train_images, train_labels,
            # broken
            # aug.flow(train_images, train_labels, batch_size = batch_size),
            steps_per_epoch=num_train // batch_size,
            epochs=epochs,
            callbacks=[cp_callback],
            validation_data=(test_images, test_labels),
            validation_steps=num_test // batch_size
        ))

        if experiment == "disagreement":
            model.save_weights((checkpoint_path).format(epoch=0))
            models.append(model)
        else:
            model.save_weights(checkpoint_path.format(epoch=0))
            models.append(model)

    aug = ImageDataGenerator(
        rotation_range=30,
        zoom_range=0.15,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.15,
        horizontal_flip=True,
        fill_mode="nearest")

    if self_train:

        if experiment == "disagreement":
            ## Augment dataset with unlabeled images

            animal_model = models[0]
            machine_model = models[1]
            animal_train_labels = all_train_labels[0]
            machine_train_labels = all_train_labels[1]
            animal_test_labels = all_test_labels[0]
            machine_test_labels = all_test_labels[1]

            # Reading only 1000 images for lack of computing power
            #unlabeled_images = read_all_images(binary_path + "unlabeled_X.bin")
            unlabeled_images = read_some_images(binary_path + "unlabeled_X.bin",
                                                int(100000 * subset_size))
            confident = True
            first = True
            # While there are still confident labelings
            while confident:
                # First train supervised model
                print("Train images and Animal, machine Label shape: ",
                      train_images.shape, animal_train_labels.shape, machine_train_labels.shape)
                print("test images and Animal, machine Label shape: ",
                      test_images.shape, animal_test_labels.shape, machine_test_labels.shape)
                # history = model.fit(
                #     aug.flow(train_images, train_labels, batch_size = batch_size),
                #     steps_per_epoch=num_train // batch_size,
                #     epochs=epochs,
                #     callbacks=[cp_callback],
                #     validation_data=(test_images, test_labels),
                #     validation_steps=num_test // batch_size
                # )
                if not first:
                    histories[0] = animal_model.fit(
                        aug.flow(train_images, animal_train_labels, batch_size = batch_size),
                        steps_per_epoch=num_train // batch_size,
                        epochs=epochs,
                        callbacks=[cp_callback],
                        validation_data=(test_images, animal_test_labels),
                        validation_steps=num_test // batch_size
                    )
                    histories[1] = machine_model.fit(
                        aug.flow(train_images, machine_train_labels, batch_size = batch_size),
                        steps_per_epoch=num_train // batch_size,
                        epochs=epochs,
                        callbacks=[cp_callback],
                        validation_data=(test_images, machine_test_labels),
                        validation_steps=num_test // batch_size
                    )
                first = False
                # print(train_images[0])


                # Predict unlabeled examples and add confident ones
                count = 0
                if (len(unlabeled_images) == 0): break
                unlabeled_predictionsA = animal_model.predict(unlabeled_images)
                unlabeled_predictionsM = machine_model.predict(unlabeled_images)
                # Converting this to probabilities:
                # print(unlabeled_predictions, unlabeled_predictions.shape)
                probs_A = tf.nn.softmax(unlabeled_predictionsA)
                probs_M = tf.nn.softmax(unlabeled_predictionsM)
                temp_labA = np.argmax(probs_A, axis = 1)
                temp_labM = np.argmax(probs_M, axis = 1)

                # Combining animal and machine labels to one
                # animal_labels = [2,4,5,6,7,8,0]
                # machine_labels = [1,3,9,10,0]
                # If both predicts other or both predict non-other,
                # it should not get selected for ST so wrong labels wont matter
                new_animal_labels = []
                new_machine_labels = []
                for i in range(len(temp_labA)):
                    new_animal_labels.append(temp_labA[i])
                    new_machine_labels.append(temp_labM[i])
                    # new_labels.append(max(animal_labels[temp_labA[i]],
                    #                       machine_labels[temp_labM[i]]))
                class_predsA = np.amax(probs_A, axis = 1)
                class_predsM = np.amax(probs_M, axis = 1)
                class_predsA = tf.reshape(class_predsA, [len(class_predsA)])
                class_predsM = tf.reshape(class_predsM, [len(class_predsM)])
                class_preds = class_predsA * class_predsM

                assert class_preds.shape == class_predsA.shape
                print("pred shape", class_predsA.shape)

                to_remove_thresh = (class_preds >= threshold)
                to_remove_xor = (temp_labA == 6) != (temp_labM == 4)
                    # XOR: one and only one of the predictions is 'other'
                to_remove = np.logical_and(to_remove_thresh, to_remove_xor)
                train_images = np.append(train_images, unlabeled_images[to_remove])
                # print(new_a / nimal_labels.dtype)
                new_animal_labels = np.array(new_animal_labels)[to_remove]
                new_machine_labels = np.array(new_machine_labels)[to_remove]
                animal_train_labels = np.append(animal_train_labels, new_animal_labels)
                machine_train_labels = np.append(machine_train_labels, new_machine_labels)
                count = np.sum(to_remove)
                unlabeled_images = unlabeled_images[np.logical_not(to_remove)]
                print("New datapoints: ", count)
                print("Remaining Datapoints:" ,unlabeled_images.shape)

                train_images = train_images.reshape(-1, 96, 96, 3)

                #print(train_images[0])

                # Recalculating num_train and batch_size:
                num_train = len(animal_train_labels)
                num_batches = math.ceil(num_train/batch_size)
                batch_size = int(num_train/num_batches)

                # No confident labelings left
                if count == 0: #< 50:
                    confident = False
                    print("Exiting loop")
            animal_model.save_weights((checkpoint_path.replace("machine","animal")).format(epoch=0))
            machine_model.save_weights((checkpoint_path).format(epoch=0))

        else:
            # Reading only 1000 images for lack of computing power
            #unlabeled_images = read_all_images(binary_path + "unlabeled_X.bin")
            unlabeled_images = read_some_images(binary_path + "unlabeled_X.bin",
                                                int(100000 * subset_size))
            confident = True
            # While there are still confident labelings
            while confident:
                # First train supervised model
                print("Train images and Label shape: ",
                      train_images.shape, train_labels.shape)
                histories[0] = model.fit(
                    aug.flow(train_images, train_labels, batch_size = batch_size),
                    steps_per_epoch=num_train // batch_size,
                    epochs=epochs,
                    callbacks=[cp_callback],
                    validation_data=(test_images, test_labels),
                    validation_steps=num_test // batch_size
                )
               # print(train_images[0])
                # Predict unlabeled examples and add confident ones
                count = 0
                if (len(unlabeled_images) == 0): break
                unlabeled_predictions = model.predict(unlabeled_images)
                # Converting this to probabilities:
                temp_lab = -1
                if experiment != "binary":
                    probss = tf.nn.softmax(unlabeled_predictions)
                    class_preds = np.amax(probss, axis = 1)
                    temp_lab = np.argmax(probss, axis = 1)
                else:
                    # print(unlabeled_predictions, unlabeled_predictions.shape)
                    class_preds = tf.nn.sigmoid(unlabeled_predictions)
                    temp_lab = tf.round(class_preds)
                class_preds = tf.reshape(class_preds, [len(class_preds)])

                # Version 1: Not vectorized
                # to_keep = list(range(len(class_preds)))
                # for i in range(len(class_preds)):
                #     if i % 50 == 0:
                #         print("Augmenting dataset " + str(i) + "/" + str(len(unlabeled_images)) + " complete")
                #     pred = class_preds[i]
                #     image = unlabeled_images[i]
                #     if np.amax(pred) >= threshold:
                #         train_images = np.append(train_images, image)
                #         train_labels = np.append(train_labels, temp_lab[i])
                #         # decrease size of unlabeled images
                #         to_keep.remove(i)
                #         count += 1
                #unlabeled_images = unlabeled_images[to_keep, :, :, :]

                # Version 2: Vectorized?
                to_remove = class_preds >= threshold
                train_images = np.append(train_images, unlabeled_images[to_remove])
                train_labels = np.append(train_labels, temp_lab[to_remove])
                count = np.sum(to_remove)
                unlabeled_images = unlabeled_images[np.logical_not(to_remove)]
                print(count)
                print(unlabeled_images.shape)

                #train_images = train_images.reshape(-1, 3, 96, 96)
                #train_images = np.transpose(train_images, (0, 3, 2, 1))
                train_images = train_images.reshape(-1, 96, 96, 3)
                #print(train_images[0])
                # Recalculating num_train and batch_size:
                num_train = len(train_labels)
                num_batches = math.ceil(num_train/batch_size)
                batch_size = int(num_train/num_batches)

                # No confident labelings left
                if count == 0: #< 50:
                    confident = False
                    print("Exiting loop")
            model.save_weights(checkpoint_path.format(epoch=0))
    # model.save(expe)



    for history in histories:
        acc = history.history['accuracy']
        val_acc = history.history['val_accuracy']

        loss=history.history['loss']
        val_loss=history.history['val_loss']

        epochs_range = range(epochs)

        plt.figure(figsize=(8, 8))
        plt.subplot(1, 2, 1)
        print("Training Accuracy:", acc)
        print("Val Accuracy", val_acc)
        plt.plot(epochs_range, acc, label='Training Accuracy')
        plt.plot(epochs_range, val_acc, label='Validation Accuracy')
        plt.legend(loc='lower right')
        plt.title('Training and Validation Accuracy')

        plt.subplot(1, 2, 2)
        plt.plot(epochs_range, loss, label='Training Loss')
        plt.plot(epochs_range, val_loss, label='Validation Loss')
        plt.legend(loc='upper right')
        plt.title('Training and Validation Loss')
        plt.show()


    if experiment == "disagreement":
        animal_labels = [2,4,5,6,7,8]
        machine_labels = [1,3,9,10]
        animal_model = models[0]
        machine_model = models[1]
        animal_predictions = animal_model.predict(test_images)
        animal_predictions = tf.nn.softmax(animal_predictions)
        print("animal predictions shape: ", animal_predictions.shape)
        animal_class_preds = np.amax(animal_predictions[:, 0:6], axis = 1)
        animal_other_preds = animal_predictions[:, 6]
        animal_class_labels = np.argmax(animal_predictions[:, 0:6], axis = 1)

        machine_predictions = machine_model.predict(test_images)
        print("machine predictions shape: ", machine_predictions.shape)
        machine_class_preds = np.amax(machine_predictions[:, 0:4], axis = 1)
        machine_other_preds = machine_predictions[:, 4]
        machine_class_labels = np.argmax(machine_predictions[:, 0:4], axis = 1)

        model_preds = []
        for i in range(len(test_labels)):
            if animal_class_preds[i] * machine_other_preds[i] > \
                    animal_other_preds[i] * machine_class_preds[i]:
                model_preds.append(animal_labels[animal_class_labels[i]])
            else:
                model_preds.append(machine_labels[machine_class_labels[i]])

        valid_accuracy = np.sum(model_preds == test_labels) / len(test_labels)
        print("validation accuracy: ", valid_accuracy)
def main(argv):

    opts, args = getopt.getopt(argv, "hi:o:", [
        "test=", "experiment=", "subset=", "self_train=", "epochs=", "batch=",
        "threshold="
    ])

    self_train = False
    subset_size = 1
    epochs = 15
    batch_size = 1000
    threshold = .75
    experiment = "default"
    binary_classification = False

    for opt, arg in opts:
        if opt == '-h':
            print(
                'self-train.py --experiment=binary --subset=1 --self_train=True --epochs=20 --batch=1000 --threshold=.75'
            )
            sys.exit()
        elif opt in ("-st", "--self_train"):
            self_train = arg.lower in ["true", "True"]
        elif opt in ("-ss", "--subset"):
            subset_size = float(arg)
        elif opt in ("-exp", "--experiment"):
            experiment = arg
            if experiment == "binary":
                binary_classification = True
        elif opt in ("-e", "--epochs"):
            epochs = int(arg)
        elif opt in ("-b", "--batch"):
            batch_size = int(arg)
        elif opt in ("-t", "--threshold"):
            threshold = float(arg)

    print(self_train)
    IMG_HEIGHT = 96
    IMG_WIDTH = 96

    binary_path = "data/stl10_binary/"

    train_images = read_all_images(binary_path + "train_X.bin")
    train_labels = read_labels(binary_path + "train_y.bin")

    test_images = read_all_images(binary_path + "test_X.bin")
    test_labels = read_labels(binary_path + "test_y.bin")

    checkpoint_path = "training/" + experiment + "-cp-{epoch:04d}.ckpt"
    checkpoint_dir = os.path.dirname(checkpoint_path)

    # Create a callback that saves the model's weights every 5 epochs
    cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                     verbose=1,
                                                     save_weights_only=True,
                                                     period=5)

    print(len(test_labels))
    print(len(train_labels))
    test_labels, test_images = convert_labels(test_labels, test_images,
                                              experiment)
    train_labels, train_images = convert_labels(train_labels, train_images,
                                                experiment)
    print(test_labels.shape)
    print(train_labels.shape)
    # exit()

    num_train = math.floor(len(train_labels) * subset_size)
    num_test = math.floor(len(test_labels) * subset_size)

    test_labels = test_labels[:num_test]
    train_labels = train_labels[:num_train]
    test_images = test_images[:num_test]
    train_images = train_images[:num_train]

    num_batches = math.ceil(num_train / batch_size)
    batch_size = int(num_train / num_batches)

    print("Adjusted batch size to " + str(batch_size))

    def plotImages(images_arr):
        fig, axes = plt.subplots(1, 5, figsize=(20, 20))
        axes = axes.flatten()
        for img, ax in zip(images_arr, axes):
            ax.imshow(img)
            ax.axis('off')
        plt.tight_layout()
        plt.show()

    #plotImages(train_images[:5])

    if experiment == "binary":
        num_classes = 1
    elif experiment == "animal":
        num_classes = 6
    elif experiment == "machine":
        num_classes = 4
    else:
        num_classes = 10

    model = Sequential([
        Conv2D(16,
               3,
               padding='same',
               activation='relu',
               input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
        MaxPooling2D(),
        Dropout(0.2),
        Conv2D(32, 3, padding='same', activation='relu'),
        MaxPooling2D(),
        Conv2D(64, 3, padding='same', activation='relu'),
        MaxPooling2D(),
        Dropout(0.2),
        Flatten(),
        Dense(512, activation='relu'),
        Dense(num_classes)
    ])

    if experiment == "binary":
        model.compile(
            optimizer='adam',
            loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
            metrics=['accuracy'])
    else:
        model.compile(optimizer='adam',
                      loss=tf.keras.losses.SparseCategoricalCrossentropy(
                          from_logits=True),
                      metrics=['accuracy'])

    model.summary()

    history = model.fit(train_images,
                        train_labels,
                        steps_per_epoch=num_train // batch_size,
                        epochs=epochs,
                        callbacks=[cp_callback],
                        validation_data=(test_images, test_labels),
                        validation_steps=num_test // batch_size)

    model.save_weights(checkpoint_path.format(epoch=0))

    ## Augment dataset with unlabeled images

    if self_train:
        unlabeled_images = read_all_images(binary_path + "unlabeled_X.bin")
        unlabeled_predictions = model.predict(unlabeled_images)
        for i in range(len(unlabeled_predictions)):
            if i % 50 == 0:
                print("Augmenting dataset " + str(i) + "/" +
                      str(len(unlabeled_images)) + " complete")
            pred = unlabeled_predictions[i]
            image = unlabeled_images[i]
            if np.amax(pred) >= .75:
                train_images = np.append(train_images, image)
                train_labels = np.append(train_labels, np.argmax(pred))
                # train_images.append(image)
                # converted_train_labels.append(np.argmax(pred))

        history = model.fit(train_images,
                            train_labels,
                            steps_per_epoch=num_train // batch_size,
                            epochs=epochs,
                            validation_data=(test_images, test_labels),
                            validation_steps=num_test // batch_size)

    # model.save(expe)

    acc = history.history['accuracy']
    val_acc = history.history['val_accuracy']

    loss = history.history['loss']
    val_loss = history.history['val_loss']

    epochs_range = range(epochs)

    plt.figure(figsize=(8, 8))
    plt.subplot(1, 2, 1)
    print("Traing Accuracy:", acc)
    print("Val Accuracy", val_acc)
    plt.plot(epochs_range, acc, label='Training Accuracy')
    plt.plot(epochs_range, val_acc, label='Validation Accuracy')
    plt.legend(loc='lower right')
    plt.title('Training and Validation Accuracy')

    plt.subplot(1, 2, 2)
    plt.plot(epochs_range, loss, label='Training Loss')
    plt.plot(epochs_range, val_loss, label='Validation Loss')
    plt.legend(loc='upper right')
    plt.title('Training and Validation Loss')
    plt.show()