Сквозной проект NLP для поиска тенденций и раскрытия тем.

Статья 1/5: Сбор 260 000 текстовых документов.

Содержание:

А. Предыстория и вариант использования

Б. Область применения этой статьи

С. Теория

C.1. Общедоступные данные, размещенные в Google BigQuery

C.2. Локальное хранение релевантных данных с помощью SQLite

Д. Код и объяснение

Моя мотивация для написания этой серии: помочь людям, которые на один или два шага отстают от меня, изучать машинное обучение. Я пишу это таким образом, чтобы вы могли щелкнуть дальше. Я программист-самоучка на Python и начал изучать науку о данных с лета 2022 года. Если что-то неясно или у вас есть предложения, не стесняйтесь обращаться ко мне здесь.

А. Предыстория и пример использования

Я завершил сквозной проект NLP (обработка естественного языка), который проанализировал 264 148 текстовых данных, собранных из StackOverflow. Я применил исследовательский анализ данных и использовал неконтролируемый алгоритм машинного обучения (ML), называемый латентным алгоритмом Дирихле (LDA). LDA используется для обнаружения повторяющихся тем из примерно 260 тыс. текстовых данных. Мой вариант использования в этом проекте — определить тенденцию тем, связанных с безопасностью в настраиваемых программах, используя обсуждения (текстовые данные) из StackOverflow. Вы можете прочитать полный отчет в формате PDF об этом проекте здесь и моем свежеиспеченном сайте здесь. Кластер темы визуализация можно посмотреть здесь.

Как видно выше, рабочий процесс машинного обучения (LDA) начинается непосредственно перед последним шагом (визуализация). Следует сделать признание: не менее 80 % моих усилий по кодированию были связаны не с машинным обучением, а со сбором, подготовкой и преобразованием данных. Необходимо учитывать некоторые соображения, чтобы решить, как управлять, хранить и подготавливать данные, чтобы обеспечить их пригодность и совместимость в качестве входных данных для рабочего процесса ML. К сожалению, во многих публикациях этим важным шагам уделяется недостаточное внимание.

B. Сфера охвата этой статьи

В этой статье я описываю только шаг «Сбор данных» (см. скриншот).

Что вы узнаете из этой статьи:

  • Сбор общедоступных данных, размещенных на Google BigQuery,
  • Фильтрация в BigQuery для получения только релевантных данных,
  • Храните текстовые данные локально, используя язык программирования SQLite + Python.

С. Теория

С.1. Общедоступные данные, размещенные в Google Bigquery

BigQuery — решение для хранилища данных от Google. BigQuery имеет свой диалект SQL и поддерживает стандартный диалект SQL. Если у вас есть опыт работы с SQL, у вас не должно возникнуть проблем с использованием BigQuery. Если нет, вы можете научиться прямо сейчас, потому что SQL необходим для специалиста по данным и, прежде всего, прост в освоении. Вы можете начать с этой статьи. Чтобы собирать общедоступные данные и преобразовывать их из BigQuery, вам просто необходимо зарегистрироваться в Google. Это бесплатно и не требует кредитной карты.

Многие публичные данные размещены на BigQuery. Общедоступные данные, которые я использовал для этого проекта, — это текстовый набор данных из обсуждений вопросов и ответов на StackOverflow.

С.2. Хранение соответствующих данных локально с помощью SQLite

После сбора, фильтрации и преобразования общедоступных данных из BigQuery необходимо хранить их локально. Что ж, это правда только наполовину для вас, потому что вы можете получить все действующие коды из этой серии статей. Но на самом деле, когда вы делаете проект, он включает в себя множество проб и ошибок в вашем коде. Поэтому просто удобнее и быстрее извлекать данные с локального компьютера. Если у вас недостаточно места для хранения, достаточно просто сохранить первые 1000 строк данных вместо всех отфильтрованных данных. Для этого проекта я скачал соответствующие данные StackOverflow (3,4 гигабайта) локально с помощью SQLite. Для просмотра базы данных SQLite необходимо установить: Браузер БД для SQLite.

С.3. Некоторые примечания

  • В этой серии статей я интенсивно использовал язык программирования Python. В основном для предварительной обработки данных и применения алгоритма машинного обучения для обнаружения тем.
  • Я использовал SQL на ранней стадии этого проекта для сбора данных. На самом последнем этапе я также использовал его для шага «Исследование данных». Потому что на тот момент было меньше суеты, и все тяжелые задачи ML Python уже были выполнены.

D. Код и объяснение

Д.1. Откройте консоль BigQuery

  • Откройте Сайт BigQuery,
  • Нажмите кнопку «Войти» (в правом верхнем углу) и используйте свою учетную запись Google,

  • После входа нажмите «Консоль» (в правом верхнем углу).

Д.2. Создайте новый проект и откройте его панель инструментов

  • Теперь создайте «Новый проект», следуя этому видео, и назовите его, например, «ProjectStackOverflow»:
  • Далее нажмите «Панель инструментов»:

  • Выберите «BigQuery» в разделе «Ресурсы».

Д.3. Открытые общедоступные наборы данных в BigQuery

  • Введите в поиск вверху «общедоступные наборы данных bigquery» и нажмите следующее:

  • Найдите следующую кнопку и нажмите ее:

  • Теперь вы можете найти все общедоступные наборы данных, размещенные в BigQuery:

  • Возможно, вы захотите добавить эту страницу в закладки для своих следующих проектов.

Д.4. Открыть набор данных StackOverflow

  • Найдите «Переполнение стека» и нажмите «Просмотреть набор данных».

  • Возможно, вы захотите отметить «stackoverflow» как свой любимый:

  • Я предлагаю вам сделать то же самое и для «bigquery-public-data», чтобы сделать общедоступные данные видимыми для вашего следующего проекта:

  • Теперь нажмите «post_questions»:

  • В новой вкладке нажмите «В новой вкладке».

  • После этого можно увидеть следующую вкладку:

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Примечание:

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

SELECT *
FROM `bigquery-public-data.stackoverflow.posts_questions` 
LIMIT 1000

Вы можете проверить набор данных posts_questionsнепосредственно, открыв «ПРЕДВАРИТЕЛЬНЫЙ ПРОСМОТР»:

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Д.5. SQL-операция в BigQuery

Это код SQL:

SELECT *
FROM `bigquery-public-data.stackoverflow.posts_questions` 
WHERE (body LIKE "%secur%" OR body LIKE "%protect%") AND
  (body LIKE "%custom%" OR body LIKE "%config%" OR
  body LIKE "%variab%" OR body LIKE "%featur%" OR 
  body LIKE "%plug%" OR body LIKE "%system_family%" OR
  body LIKE "%product_family%" OR body LIKE "%software_family%")
ORDER BY creation_date DESC

Пояснение к предыдущему запросу:

  1. SELECT *: Показать мне данные из всех (*) столбцов …
  2. FROM '...' : … таблица posts_questions общедоступного набора данных StackOverflow …
  3. WHERE: … со следующими требованиями: напр. столбец body содержит слово «защищать» или «защищать» и т. д.
  4. ORDER BY creation_date DESC: Сортировать всю строку по убыванию на основе ее creation_date.

После выполнения запроса вы можете сохранить результат как «таблицу BigQuery»:

После этого вам необходимо:

  1. Выберите один Data set или создайте его, если вы его еще не создали. На скриншоте ниже я выбрал один существующий файл Data set.
  2. Дайте имя новой таблице. В этом примере я назвал его: posts_questions_filtered. Я предлагаю вам использовать то же имя, что и на снимке экрана ниже, чтобы вы могли следить за моими следующими статьями, не находя, какое имя вы использовали раньше.

Теперь вы можете найти новую экспортированную таблицу на левой боковой панели.

Д.6. Создайте и загрузите ключ учетной записи облачной службы Google (файл JSON)

Ключ учетной записи Google необходим для загрузки данных программно. Следуйте следующему видео (или этой ссылке), чтобы сгенерировать сервисный аккаунт. Выберите роль owner (отметьте 1:50) и загрузите файл JSON (2:55). Будьте осторожны, чтобы случайно не поделиться файлом JSON (например, из-за контроля версий Git).

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

В следующем разделе мы начнем с импорта таблицы BigQuery в локальную базу данных SQLite. Для этого нам понадобится следующий код Python в качестве основы:

  1. Код Python для скачивания таблицы BigQuery (D.7),
  2. Код Python для сохранения скачанной таблицы в базе данных SQLite (D.8),
  3. Код Python для объединения двух предыдущих операций (D.9).

Я объясняю необходимый код Python с высокого уровня, так как (я посчитал) есть › 2500 строк кода. Поэтому я прикрепляю ссылку на весь необходимый код здесь и поясняю важные части. Если у вас есть вопросы, не стесняйтесь обращаться ко мне: здесь.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Д.7. Импорт таблицы BigQuery в локальный SQLite

Полный код: здесь.

...
class BigqueryOperation():
    def __init__(self, PATH_GOOGLE_CREDENTIAL:str) -> None:
        # Read credential.
        self._credentials = service_account.Credentials.from_service_account_file(\
            PATH_GOOGLE_CREDENTIAL)
        # Construct a BigQuery client object.
        self._client = bigquery.Client(credentials=self._credentials)
        self.last_request_schema = []
    def query_request(self, QUERY:str) -> pd.DataFrame:
        # Make an API request.
        query_job = self._client.query(QUERY)
        query_result = query_job.result()
        # Get the schema and save as self.last_request_schema
        self.last_request_schema = []
        for i in range(len(query_job.result().schema)):
            column_dict = query_job.result().schema[i].to_api_repr()
            column_str = " ".join(column_dict.values())
            self.last_request_schema.append(column_str)
        # Create an iterable of pandas DataFrames, to process the table as a 
        # stream by using: .to_dataframe_iterable().
        df_iterable = query_result.to_dataframe_iterable()
        return df_iterable

Описание кода Python из предыдущей ссылки:

  1. Он содержит класс Python для получения конкретной таблицы из BigQuery.
  2. При инициализации класса вам необходимо сохранить путь к файлу ключа учетной записи Google, сгенерированный на шаге D.6, в переменной PATH_GOOGLE_CREDENTIAL.
  3. При выполнении query_request требуется код BigQuery в качестве входных данных QUERY. Ваше утверждение FROM может отличаться в зависимости от имен, которые вы дали (относится к этому снимку экрана) из шага D.5.
if __name__ == "__main__":
    PATH_GOOGLE_CREDENTIAL = "../Credentials/service-account-file.json"
    QUERY = """
        SELECT *
        FROM `projectstackoverflow.dataset_stackoverflow.posts_questions_filtered`
        ORDER BY creation_date DESC
        LIMIT 100
    """
...
    bigquery_object = BigqueryOperation(PATH_GOOGLE_CREDENTIAL)

Стоит отметить:

df_iterable = query_result.to_dataframe_iterable()

Предыдущий код необходим, особенно при работе с большими данными. Это как сказать:

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

Прежде чем перейти к следующей части, проверьте, может ли код работать на вашем компьютере. Всегда разделяйте и властвуйте свои большие проекты на более мелкие части и тестируйте их один за другим, прежде чем объединять их вместе и тестировать вместе!

Д.8. Хранить данные в локальной базе данных SQLite

Полный код: здесь. Он содержит класс Python для всех операций SQLite. На этом этапе вам следует скачать Просмотрщик SQLite.

При работе с БД большую часть времени вам нужно либо записать таблицу в БД, либо прочитать таблицу. Для написания таблицы необходимо выполнить следующие шаги:

...
sqlite_handler = SqliteOperation(PATH_SQLITE)
sqlite_handler.create_table(NAME_TABLE, df_schema)
...
for i in df_iterable:
    ...
    sqlite_handler.insert_table_from_df(NAME_TABLE, i)
...
  1. Выполните метод create_table. Этот шаг необходим только при создании таблицы. Если у вас уже есть таблица для ваших данных, вы можете пропустить этот шаг. Этот метод требует следующих двух входных данных: а) имя для новой таблицы, б) схема таблицы, хранящаяся в списке. Схема таблицы содержит информацию о том, какой формат данных имеет каждый столбец. (строка, целое число и т. д.). В следующем разделе мы просто скопируем ту же схему из BigQuery, а не создадим ее вручную.
  2. Оператор for в блоке кода выше перебирает каждую строку данных (в формате кадра данных Pandas) и выполняет метод insert_table_from_df. Этот метод также оптимизирован, так что он «временно сохраняет» 100 строк данных в памяти и впоследствии сохраняет их в БД, совершая commit(). (Проверьте оператор if в следующем блоке кода). Если вместо этого он фиксируется после получения строки данных, сохранение данных займет слишком много времени.
def insert_table_from_df(self, name, df_to_insert:pd.DataFrame) -> None:
    # Wraper for insert_table method for dataframe input.
    count = 0
    commit_ = False
    df_to_insert = self.repair_df_format(df_to_insert)
    label = list(df_to_insert.columns)
    for i in df_to_insert.itertuples(index=False):
        self.insert_table(name, label, list(i), commit_)
        # Divide and conquer commiting:
        count += 1
        if count == 100:
            commit_, count = True, 0
        else:
            commit_ = False
    self._connect.commit()
    # print("*** Query commited successfully.")
    return

Д.9. Объедините предыдущие 2 операции (D.7 и D.8)

Полный код: здесь.

from a_requesting_bigquery import BigqueryOperation
from b_sqlite_operation import SqliteOperation
import time

PATH_GOOGLE_CREDENTIAL = "../Credentials/service-account-file.json"
QUERY = """
    SELECT *
    FROM `projectstackoverflow.dataset_stackoverflow.posts_questions_filtered`
    ORDER BY creation_date DESC
"""
NAME_TABLE = "raw_datas"
PATH_SQLITE = "./DB/StackOverflow_Medium.sqlite"

bigquery_handler = BigqueryOperation(PATH_GOOGLE_CREDENTIAL)
df_iterable = bigquery_handler.query_request(QUERY)
df_schema = bigquery_handler.last_request_schema

sqlite_handler = SqliteOperation(PATH_SQLITE)
sqlite_handler.create_table(NAME_TABLE, df_schema)

count = 0
total_row = 0
for i in df_iterable:
    total_row += len(i)
    print("{}. Total row so far: {}.".format(str(count), str(total_row)))
    sqlite_handler.insert_table_from_df(NAME_TABLE, i)
    del i
    count += 1
    time.sleep(3)
print("Finished")

Перед выполнением кода из предыдущей ссылки необходимо обновить следующие переменные: PATH_GOOGLE_CREDENTIAL, QUERY, NAME_TABLE, PATH_SQLITE. Ваш оператор FROM для переменной QUERY может отличаться в зависимости от имен, которые вы дали (относится к этому снимку экрана) из шага D.5. Если вы сделали именно так, как описано в этой статье, вы можете просто скопировать и вставить последний блок кода и сохранить его под именем c_bigquery_sqlite.py.

Тест:

Если вы хотите выполнить этот проект с меньшим объемом данных (вместо всех доступных данных), вы также можете изменить QUERY, чтобы загружать данные только за 2017–2022 годы. Google (или, возможно, сегодня ChatGPT) — ваш лучший друг, если вы не знаете, как решить проблему программирования. Я раскрою ответ в следующей статье.

Я надеюсь, что вам будет полезно это руководство. Если что-то неясно или у вас есть предложения, не стесняйтесь обращаться ко мне здесь или использовать раздел комментариев.

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