как сделать мою логистическую регрессию быстрее - PullRequest
0 голосов
/ 13 марта 2019

Я должен сделать простую логистическую регрессию (только в numpy, я не могу использовать pytourch или тензор потока).

Данные: часть MNIST

Цель: у меня должно быть точность около 86% .

К сожалению, у меня есть только около 70% , и моя функция потерь колеблется странно.

Должно быть, что-то не так с функциями: t_cross_entropy или np_cross_entropy_grad

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

Не могли бы вы помочь?(ниже у вас есть код и диаграммы)

Я МОГУ ИЗМЕНИТЬ ТОЛЬКО функции: np_linear, np_softmax, np_cross_entropy, np_cross_entropy_grad (и в конечном итоге в классе NumpyLogisticRegression только функция перенаправления)

1.загрузить часть MINST

# Import MNIST dataset

import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm

%matplotlib inline

def load_dataset(dataset_name):
    data = np.load('data/{}/{}.npz'.format(dataset_name.upper(), 
dataset_name))
    return data['X_train'], data['y_train'], data['X_test'], 
data['y_test']

X_train, y_train, X_test, y_test = load_dataset('mini_mnist')

f, ax = plt.subplots(1, 10, sharex='col', sharey='row',figsize=(18, 16))
for a in ax:
    a.imshow(X_train[np.random.randint(X_train.shape[0])].reshape(28, 
28), cmap='gray')
plt.show()

X_train = np.c_[np.ones(X_train.shape[0]), X_train]
X_test = np.c_[np.ones(X_test.shape[0]), X_test]
print("train data shape: {}, test data shape: 
{}".format(X_train.shape, X_test.shape))

2.основной класс и функции

def np_linear(x, a):
    return np.dot(x, a.transpose())
    '''
    Calculate l(x;a) in BxK

    :param x: Bx(D+1) input data
    :param a: Kx(D+1) weight matrix
    '''
def np_softmax(l):
    exps = np.exp(l - np.max(l))
    return exps / np.sum(exps)
   '''
    Calculate p(l) in BxK

    :param l: BxK logits
    '''

def np_cross_entropy(p, y):
    m = y.shape[0]
    log_likelihood = -np.log(p[range(m),y])
    loss = np.sum(log_likelihood) / m
    return loss
    '''
    Calculate L(p,y)

    :param p: BxK predictions
    :param y: B true labels
    '''

def np_cross_entropy_grad(p, y, x):
    m = y.shape[0]
    grad = p
    grad[range(m),y] -= 1
    grad = grad/m
    grad = grad.transpose()
    return np.dot(grad, x)

'''
Calculate dL/da in Kx(D+1)

:param p: BxK predictions
:param y: B true labels
:param x: Bx(D+1) input data
'''

class NumpyLogisticRegression:

    def __init__(self, n_classes, n_epochs, input_size, learning_rate=0.1, batch_size=256):
        self.A = np.zeros((n_classes, input_size))
        self.learning_rate = learning_rate
        self.batch_size = batch_size
        self.input_size = input_size
        self.n_classes = n_classes
        self.n_epochs = n_epochs

    def forward(self, x):
        return np_softmax(np_linear(x, self.A))

    def train(self, X, Y, X_test=None, y_test=None):
        loss, train_accuracy, test_accuracy = [], [], []

        for e in tqdm(range(self.n_epochs)):

            perm = np.random.permutation(len(X))
            X, Y, = X[perm], Y[perm]

            for batch in range(len(X) // self.batch_size):
                x = X[batch * self.batch_size:(batch + 1) * self.batch_size]
                y = Y[batch * self.batch_size:(batch + 1) * self.batch_size]

                p = self.forward(x)
                l = np_cross_entropy(p, y)

                loss.append(l)
                train_accuracy.append(self.test(x, y))
                if X_test is not None and y_test is not None:
                    test_accuracy.append(self.test(X_test, y_test))

                grad_A = np_cross_entropy_grad(p, y, x)
                self.A -= grad_A * self.learning_rate

        return loss, train_accuracy, test_accuracy

    def test(self, X, Y):
        p = np.argmax(self.forward(X), axis=1)
        return np.mean(p == Y)

3.Тест

clf = NumpyLogisticRegression(n_classes=10, n_epochs=10, input_size=785)
loss, train_accuracy, test_accuracy = clf.train(X_train, y_train, X_test, y_test)

4.Графики (без кода, только результаты)

As you see sth is wrong...

1 Ответ

0 голосов
/ 13 марта 2019

Проблема была в np_softmax функции, она должна выглядеть следующим образом:

def np_softmax(l):
    exps = np.exp(l - np.max(l))
    return exps / np.sum(exps, axis=1).reshape(-1,1)

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

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