избегая итераций с использованием умных точек / матемул на большом наборе данных - PullRequest
1 голос
/ 14 апреля 2019

Я пытаюсь написать мультиклассовый алгоритм персептрона для набора данных MNIST.

Теперь у меня есть следующий код, который работает, но из-за того, что он повторяется 60k раз, он работает медленно.

weights - это размер - (785,10)

def multiClassPLA(train_data, train_labels, weights):
    epoch_err = []  # will hold the misclassified ratio for each epoch
    best_weights = weights
    best_error = 1

    for epoch in range(EPOCH):
        err = 0
        # randomize the data before each epoch
        train_data, train_labels = randomizeData(train_data, train_labels)
        for x, y in zip(train_data, train_labels):
            h = oneVsAllLabeling_(np.dot(weights, x))
            diff = (y - h) / 2
            x = x.reshape(1, x.shape[0])
            diff = diff.reshape(CLASSES, 1)

            update_step = ETA * np.dot(diff, x)
            weights += update_step

    return weights

oneVsAllLabeling_ (X) возвращает вектор, который содержит 1 в argmax и -1в другом месте.Конечно, метки истины имеют ту же форму.

с этим алгоритмом я получаю точность ~ 90%, безопасно, но медленно.после дальнейшего изучения проблемы я обнаружил, что могу улучшить код, используя умножение массива / матрицы.

, поэтому я начал делать следующее:

def oneVsAllLabeling(X):
    idx = np.argmax(X, axis=1)
    mask = np.zeros(X.shape, dtype=bool)
    mask[np.arange(len(idx)),idx] = 1
    out = 2 * mask - 1
    return out.astype(int)

def zeroOneError(prediction):
    tester = np.zeros((1, CLASSES))
    good_prediction = len(np.where(prediction == tester))
    return len(prediction) - good_prediction

def preceptronModelFitting(data, weights, labels, to_print, epoch=None):
    prediction = np.matmul(data, weights)
    prediction = oneVsAllLabeling(prediction)
    diff = (prediction - labels) / 2
    error = zeroOneError(diff)
    accuracy = error / len(data)
    if to_print:
        print("Epoch: {}. Loss: {}. Accuracy: {}".format(epoch, error, accuracy))
    return prediction, error, accuracy

def multiClassPLA2(train_data, train_labels, test_data, test_labels, weights):
    predicted_output = np.zeros((1, CLASSES))

    train_loss_vec = np.array([])
    train_accuracy_vec = np.array([])
    test_loss_vec = np.array([])
    test_accuracy_vec = np.array([])

    for epoch in range(EPOCH):
        # randomize the data before each epoch
        train_data, train_labels = randomizeData(train_data, train_labels)
        train_prediction, train_error, train_accuracy = preceptronModelFitting(train_data, weights, train_labels, to_print=False)
    return weights

после вызова preceptronModelFitting () Я получаю матрицу размером (60k, 10), каждая запись которой имеет следующую форму:

train_prediction[0]=[0,0,1,0,0,-1,0,0,0,0]

, а данные имеют форму (60k, 785)

Теперь, что мне нужно сделать, это, по возможности, умножить каждую строку на каждую из записей данных и суммировать так, чтобы в итоге получилась матрица размером (785,10), которую я могу обновить с ее помощьюстарый набор весов.

, который почти эквивалентен тому, что я делаю в неэффективном алгоритме, единственное отличие состоит в том, что я обновляю веса при каждом новом вводе данных, а не после просмотра всех данных.

Спасибо!

1 Ответ

0 голосов
/ 15 апреля 2019

Хорошо, вы выполнили большую часть работы, и даже у вас была часть ответа в заголовке.

np.matmul(X.T, truth - prediction)

Используя это, вы получите то, что вы хотите, в одну строку.обратите внимание, что это основано на том факте, что на самом деле истина, предсказание, X такие, как вы упомянули.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...