Автор оригинала: Waqas Bukhari PhD.
Многомерные наборы данных возникают в различных областях, начиная от вычислительной рекламы и заканчивая обработкой естественного языка. Обучение в таких больших измерениях может быть ограничено с точки зрения вычислений и/или памяти. С этой целью для преобразования в пространстве с меньшей размерностью используются методы уменьшения размерности, такие как (линейный/нелинейный) анализ главных компонент или обучение многообразиям. Однако эти методы уменьшения размерности иногда не могут быть применимы, например, в разреженных наборах данных, которые имеют независимые объекты, и данные лежат в нескольких многомерных многообразиях.
В этой статье мы обсудим и реализуем подход к обучению с использованием таких разреженных многомерных наборов данных. Размерность данных и размер данных-это два аспекта этих проблем. Чтобы уменьшить размерность данных, хеширование объектов предлагает масштабируемое и вычислительно эффективное представление объектов. Большой набор данных все еще может создавать ограничения на вычислительные ресурсы и память на персональном компьютере. С этой целью мы используем мини-пакетный градиентный спуск для итеративного обучения модели.
В этой статье мы используем инструменты из Python, такие как Pandas, Numpy и Scikit-Learn, для использования хэширования функций и мини-пакетного обучения с разреженными, многомерными и большими наборами данных. Фрагменты кода с подробными комментариями включены для практической реализации в рамках науки о данных python.
Создание и хранение данных
Мы демонстрируем практическое использование хеширования функций и мини-пакетного обучения с использованием задачи бинарной классификации. Для решения этой проблемы создается поддельный набор данных, содержащий 1,0 миллиона точек данных. Каждая точка данных в наборе данных содержит пакет буквенно-цифровых маркеров вместе с меткой. При создании набора данных мы сначала создали 65464 буквенно-цифровых объекта путем случайной выборки из набора алфавитов и 10 цифр. Во-вторых, мы сгенерировали данные для каждого из двух классов (0 и 1) отдельно, используя половину числа функций, т. Е. исключительно 32732. Чтобы создать разреженность, ни одна из функций не назначается более чем 0,3% данных. Обратите внимание, что наше создание данных приводит к совершенно разделяемым классам.
Мини-пакетное обучение с хешированием функций
Следующий код демонстрирует практическую реализацию итеративного обучения с хэшированием функций. Функциональный поезд(модель, линии) обновляет модель в течение 1 эпохи с помощью мини-пакетного обучения. Обучающий набор данных хранится в строках в виде списка строк, каждая из которых является записью. Это универсальная функция, которая применяется к любому классу модели в sklearn, поддерживающему метод partial_fit (). Популярными вариантами моделей классификации, поддерживающими функцию partial_fit (), являются логистическая регрессия, машины опорных векторов и искусственные нейронные сети. Эта функция поддерживает мини-пакетное обучение; каждая партия размером 1000 образцов. На каждой итерации функция создает фрейм данных pandas из 1000 выборок из строк, вычисляет хэширование объектов в соответствии с заранее определенными размерами объектов и обновляет модель.
Вторая функция hash_representation(df) используется функцией train (). Он вычисляет хеширование объектов на входных строках, которые хранятся в виде столбца во входном df. Вычисленное представление объектов объединяется с фреймом данных df и возвращается.
См.Подробные комментарии в функциях для лучшего понимания.
def hash_representation(df): def vectorize(line): ''' This function transforms a line comprising bag to words to its hash representation. Input to this function is a line that comprises , separated words. output is a numpy array which is the hash representation of line according to a hash template (global object). ''' # Construct a dictionary comprising each word in the line as keys and 1 as its value. D = [{key:1 for key in line.split('\n')[0].split(',')}] # tranform D to a numpy array according to a hash template h. return h.transform(D).toarray()[0] # Obtain hash represntation of input strings. s = df['inputs'].apply(vectorize) # Giving non-numeric names to the resulting data frame. columns = ['col_'+str(i) for i in range(len(s.values[0]))] new_df = pd.DataFrame.from_items(zip(s.index, s.values), orient='index', columns=columns) new_df['labels'] = df['labels'] # Returning dataframe that has hash representation of inputs as features along with class labels. return new_df
def train(model, lines): ''' This function takes updates the model over 1 epoch of training data. Inputs to this function are: model ~ An sklearn model object over which partial_fit() method is valid. lines ~ a list of strings and each string is a record, example or a measurement. Output of this function is model ~ an updated model. ''' ''' We construct a pandas DataFrame out of these lines and use its str functionality to create new columns; one for input strings and the other for output labels. ''' df = pd.DataFrame(lines, columns=['raw_data']) df['labels'] = df['raw_data'].str.split(',').apply(lambda x:x[0]).astype(int) #%[0][0] df['inputs'] = df['raw_data'].str.split(',').apply(lambda x:x[1]) #%[0][0] del df['raw_data'] ''' We shuffle the data to ensure randomness to avoid any cycles in training. ''' df = shuffle(df) ''' We specify the batch size that specifies the data size over which model update is based in one iteration. ''' batch_size = 1000 "total number of batches" total_batches = math.ceil(df.shape[0] / batch_size) # Iterating over each batch. for batch_numb in range(total_batches): st = batch_numb * batch_size # starting index (inclusive) of the batch. en = (1+batch_numb) * batch_size # End index (exclusive) of the batch. ''' Last batch may comprise data points less than the batch_size. Under such a scenario, the batch_size comprises remaining elements that are less than the batch_size and we modify the End index to be the size of the lines. ''' en = min(en, df.shape[0]) '''For the subset of lines comprising current batch, we construct a new data frame that comprises hash representation of the inputs along with outputs. ''' tmp_df = hash_representation(df.iloc[st:en]) tmp_labels = tmp_df['labels'].copy() del tmp_df['labels'] # model update using current batch. model.partial_fit(np.array(tmp_df), np.array(tmp_labels), classes=[0,1]) # returning model after updating with 1 epoch. return model
Выбор модели и гиперпараметры
Чтобы продемонстрировать эффективность нашего Мини-пакетного обучения с хешированием функций подхода, мы разделили наш набор данных на 80% обучения, 10% проверки и 10% тестирования. следует отметить, что 10% тестовых данных содержат 100000 образцов, что достаточно для оценки производительности. Мы оценили логистическую регрессию, машину опорных векторов и искусственные нейронные сети с несколькими вариантами архитектуры. Было обнаружено, что искусственные нейронные сети дают наилучшую производительность проверки. В то время как производительность на более глубоких архитектурах немного выше, ANN с 1 скрытым слоем, состоящим из 100 нейронов, обеспечивает производительность проверки; достаточно хорошую, чтобы продемонстрировать наши идеи. Мы также обнаружили, что производительность валидации лишь незначительно меняется по сравнению с первой эпохой; предполагая, что производительность валидации с 1 эпохой является репрезентативной для производительности модели. В наших последующих экспериментах мы использовали ANN с 1 скрытым слоем, состоящим из 100 нейронов, в качестве нашей модели, и обучение проводилось всего за 1 эпоху.
Оптимальный размер хеширования
Хеширование объектов может привести к столкновению хеширования , которое относится к двум различным точкам данных, дающим одно и то же представление хеширования. Столкновение образцов одного класса с образцами другого ухудшает точность классификации. По мере увеличения размера хеширования все меньшие и меньшие различия во входных данных приводят к различным представлениям хеширования; следовательно, количество столкновений уменьшается. Недостатки в обучении, возможное смещение модели и коллизии хэширования являются важными источниками шума в этой задаче бинарной классификации. Хотя недостатки в обучении и возможная предвзятость модели могут быть исследованы, мы стремимся продемонстрировать влияние измерений хеширования на эффективность классификации. Более высокий размер хеширования, вероятно, повышает точность классификации, хотя и за счет вычислений и памяти.
Ниже приведен шаблон хеширования объектов из sklearn.feature_extraction с размером хеширования в качестве параметра.
h = FeatureHasher(n_features=hashing_dimension)
Мы провели численные эксперименты с различными размерами хеширования и получили следующую точность проверки.
1600 | 73.9% |
3200 | 80.4% |
6400 | 86.8% |
12800 | 91.6% |
19200 | 93.5% |
25600 | 94.8% |
Обратите внимание из таблицы, что производительность проверки улучшается с измерением хеширования, однако при уменьшении отдачи. Более высокие размеры хэширования приводят к вычислительно более дорогостоящему обучению и требуют большего объема памяти или меньшего размера пакета. Следовательно, оптимальный выбор размера хеширования зависит от вычислительных ресурсов и точки, после которой отдача незначительна. Для нашего случая мы выбрали размер хеширования 12800 и оценили производительность теста, которая составила 91,4%.
Выводы
Мы представили хеширование функций; масштабируемый и надежный метод уменьшения размерности, который может быть единственным вариантом уменьшения размерности в определенных задачах и может обеспечить более высокую производительность по сравнению с популярным PCA или многомерным обучением. В рамках sklearn также демонстрируется комплексная структура для хеширования функций с помощью мини-пакетного обучения. Наши численные эксперименты продемонстрировали эффективность нашего подхода и реализации.