Существует ли более быстрый способ получения локального двоичного шаблона набора данных MNIST? - PullRequest
3 голосов
/ 07 мая 2019

Мне нужно знать, есть ли более быстрый способ получить LBP и полученные гистограммы набора данных MNIST. Это будет использоваться для распознавания рукописного текста через модель, которую я еще не определил ..

Я загрузил набор данных MNIST и разделил его на обучающие наборы x, y и тестовые наборы x, y на основе tensorflow учебных пособий.

Затем я использовал cv2 для инвертирования изображений.

Оттуда я определил функцию, используя skimage, чтобы получить LBP и соответствующую гистограмму входного изображения

Наконец, я использовал классический цикл for для итерации по изображениям, получения их гистограмм, сохранения их в отдельном списке и возврата нового списка и неизмененного списка меток как обучающих, так и тестовых наборов.

Вот функция загрузки набора данных MNIST:

def loadDataset():
    mnist = tf.keras.datasets.mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    # should I invert it or not?
    x_train = cv2.bitwise_not(x_train)
    x_test = cv2.bitwise_not(x_test)

    return (x_train, y_train), (x_test, y_test)

Вот функция для получения LBP и соответствующей гистограммы:

def getLocalBinaryPattern(img, points, radius):
    lbp = feature.local_binary_pattern(img, points, radius, method="uniform")
    hist, _ = np.histogram(lbp.ravel(), 
                bins=np.arange(0, points + 3),
                range=(0, points + 2))

    return lbp, hist

И, наконец, вот функция для перебора изображений:

def formatDataset(dataset):
    (x_train, y_train), (x_test, y_test) = dataset

    x_train_hst = []
    for i in range(len(x_train)):
        _, hst = getLocalBinaryPattern(x_train[i], 8, 1)
        print("Computing LBP for training set: {}/{}".format(i, len(x_train)))
        x_train_hst.append(hst)

    print("Done computing LBP for training set!")

    x_test_hst=[]
    for i in range(len(x_test)):
        _, hst = getLocalBinaryPattern(x_test[i], 8, 1)
        print("Computing LBP for test set: {}/{}".format(i, len(x_test)))
        x_test_hst.append(hst)

    print("Done computing LBP for test set!")

    print("Done!")

    return (x_train_hst, y_train), (x_test_hst, y_test)

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

1 Ответ

1 голос
/ 08 мая 2019

Я не думаю, что есть простой способ ускорить итерацию по изображениям. Можно было бы ожидать, что использование vectorize или apply_along_axis в NumPy улучшит производительность, но эти решения на самом деле медленнее, чем цикл for (или понимание списка).

Демо

Различные альтернативы для перебора изображений:

def compr(imgs):
    hists = [getLocalBinaryPattern(img, 8, 1)[1] for img in imgs]
    return hists

def vect(imgs):
    lbp81riu2 = lambda img: getLocalBinaryPattern(img, 8, 1)[1]
    vec_lbp81riu2 = np.vectorize(lbp81riu2, signature='(m,n)->(k)')
    hists = vec_lbp81riu2(imgs)
    return hists

def app(imgs):
    lbp81riu2 = lambda img: getLocalBinaryPattern(img.reshape(28, 28), 8, 1)[1]
    pixels = np.reshape(imgs, (len(imgs), -1))
    hists = np.apply_along_axis(lbp81riu2, 1, pixels)
    return hists

Результаты:

In [112]: (x_train, y_train), (x_test, y_test) = loadDataset()

In [113]: %timeit -r 3 compr(x_train)
1 loop, best of 3: 14.2 s per loop

In [114]: %timeit -r 3 vect(x_train)
1 loop, best of 3: 17.1 s per loop

In [115]: %timeit -r 3 app(x_train)
1 loop, best of 3: 14.3 s per loop

In [116]: np.array_equal(compr(x_train), vect(x_train))
Out[116]: True

In [117]: np.array_equal(compr(x_train), app(x_train))
Out[117]: True
...