#python #numpy
#python #numpy
Вопрос:
Я пытаюсь написать многоклассовый алгоритм персептрона для набора данных MNIST.
теперь у меня есть следующий код, который работает, но из-за того, что он повторяется 60 тысяч раз, он работает медленно.
вес — это размер — (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:
Хорошо, вы выполнили большую часть работы, и даже у вас была часть ответа в вашем названии.
np.matmul(X.T, truth - prediction)
Используя это, вы получите то, что вы хотите, в одной строке.
обратите внимание, что это основано на том факте, что действительно истина, предсказание, X, как вы упомянули.