Работа с файлами в Google Colab | Программирование на Питоне

Работа с файлами в Google Colab

Все курсы > Программирование на Питоне > Занятие 4

Для построения модели нам нужны данные. И очень часто эти данные содержатся во внешних файлах. Мы уже столкнулись с этим, когда работали с рекомендательными системами и временными рядами. Предлагаю сегодня рассмотреть этот вопрос более детально.

Содержание занятия

Общее описание процесса

работа с внешними файлами в Google Colab

В целом работа с файлами в Google Colab состоит из следующих этапов.

  • Этап 1. Подгрузка файлов с локального компьютера на сервер Google
  • Этап 2. Чтение файла
  • Этап 3. Построение модели и прогноз
  • Этап 4. Сохранение результата в новом файле на сервере Google
  • Этап 5. Скачивание обратно на жесткий диск

Пройдемся по каждому из них. Но прежде поговорим про данные.

Датасет «Титаник»

На этом занятии предлагаю взять датасет о пассажирах корабля «Титаник», который, как известно, затонул в 1912 году при столкновении с айсбергом. Часть пассажиров выжила, но многие, к сожалению, погибли. В приведенном ниже датасете собрана информация о самих пассажирах (признаки), а также о том, выжили они или нет (целевая переменная).

датасет "Титаник" с платформы Kaggle

Данные уже разделены на обучающую и тестовую выборки. Скачаем их.

Также откроем ноутбук к этому занятию

Этап 1. Подгрузка файлов в Google Colab

Если внешние файлы хранятся на локальном компьютере, то нам нужно подгрузить их в так называемое «Сессионное хранилище» (session storage, по сути, сервер Google).

Слово «сессионное» указывает на то, что данные, как я уже говорил, хранятся временно и после завершения очередной сессии стираются.

Подгрузить данные с локального компьютера можно двумя способами.

Способ 1. Вручную через вкладку «Файлы»

Этот способ мы использовали до сих пор. В качестве напоминания приведу скриншоты подгрузки файла train.csv.

подгрузка внешних файлов в Google Colab вручную
подгрузка внешних файлов в Google Colab вручную 2

Способ 2. Через объект files библиотеки google.colab

К объекту files мы применяем метод .upload(), который передает нам словарь. Ключами этого словаря будут названия файлов, а значениями — сами подгруженные данные. Приведем пример с файлом test.csv.

Нам будет предложено выбрать файл на жестком диске.

подгрузка внешних файлов в Google Colab с помощью библиотеки google.colab и метода .upload()
подгрузка внешних файлов в Google Colab с помощью библиотеки google.colab и метода .upload() 2

Все что идет после двоеточия ( :) и есть наш файл. Он содержится в формате bytes, о чем свидетельствует буква b перед строкой файла (подробнее об этом ниже).

Этап 2. Чтение файлов

После загрузки оба файла (train.csv и test.csv) оказываются в сессионном хранилище в папке под названием /content/.

результат подгрузки данных с локального компьютера в Google Colab

Просмотр содержимого в папке /content/

Модуль os и метод .walk()

Для того чтобы просмотреть ее содержимое внутри ноутбука, мы можем воспользоваться модулем os (отвечает за взаимодействие Питона с операционной системой) и, в частности, методом .walk() (позволяет «пройтись» по содержимому конкретной папки).

Первые два файла и есть наши данные. В скрытой подпапке /.config/ содержатся служебные файлы, а в подпапке /sample_data/ — примеры датасетов, хранящиеся в Google Colab по умолчанию.

Команда !ls

Кроме того, если нас интересуют только видимые файлы и папки, мы можем воспользоваться командой !ls (ls означает to list, т.е. «перечислить»).

Подобным образом мы можем заглянуть внутрь папки sample_data.

Теперь прочитаем файл сначала из переменной uploaded, а затем напрямую из папки /content/.

Чтение из переменной uploaded

Как мы уже сказали выше, в словаре uploaded файл содержится в формате bytes.

Основная особенность: информация в объекте bytes представляет собой последовательность байтов (byte string), в то время как обычная строка — это последовательность символов (character string). Компьютер понимает первый тип, мы (люди) — второй.

Для того чтобы прочитать информацию из объекта bytes, ее нужно декодировать (decode). Если мы захотим вернуть ее обратно в объект bytes, соответственно, закодировать (encode).

переход от строки к объекту bytes и обратно

Таким образом, чтобы прочитать данные напрямую из словаря uploaded, вначале нам нужно преобразовать эти данные в обычную строку.

Выведем первые 35 значений.

Если разбить строку методом .split() по символам \r (возврат к началу строки) и \n (новая строка), то на выходе мы получим список.

Пройдемся по этому списку и выведем первые четыре значения.

Вот нам и пригодился оператор break. Как мы видим, первая строка — это заголовок (header), остальные — информация по каждому из пассажиров.

Использование функции open() и конструкции with open()

Такого же результата можно добиться с помощью базовой функции open().

Обратите внимание, здесь мы читаем файл непосредственно из папки /content/. Декодировать файл уже не нужно.

Функция open() возвращает объект, который используется для чтения и изменения файла. Откроем файл train.csv.

Вначале попробуем применить метод .read().

Для наших целей метод .read() не очень удобен. Будет лучше пройтись по файлу в цикле for.

Еще один способ — использовать конструкцию with open(). В этом случае специально закрывать файл не нужно.

Чтение через библиотеку Pandas

Вероятно наиболее удобный и подходящий для наших целей способ чтения файлов — это преобразование напрямую в датафрейм библиотеки Pandas. С этим методом в целом мы уже знакомы.

чтение файла train.csv с помощью функции read_csv()
чтение файла test.csv с помощью функции read_csv()

Примечание. На скриншотах приведена лишь часть датафреймов, полностью их можно посмотреть в ноутбуке⧉.

Этап 3. Построение модели и прогноз

Давайте ненедолго отвлечемся от работы с файлами и построим несложную модель, которая предскажет погиб пассажир (обозначим этот факт через 0) или выжил (1). Прежде всего, концептуально обсудим, что нам нужно сделать.

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

  • Шаг 1. Обработать и проанализировать данные
  • Шаг 2. Разделить обучающую выборку (train) на признаки (X_train) и целевую переменную (y_train)
  • Шаг 3. Обучить модель логистической регрессии
  • Шаг 4. Подготовить тестовые данные (X_test) и сделать прогноз

А теперь обо всем по порядку.

Шаг 1. Обработка и анализ данных

Исследовательский анализ данных (EDA)

Напомню, что основная задача EDA — выявить взаимосвязь между признаками и целевой переменной. Воспользуемся методом .info(), чтобы обобщенно посмотреть на наши данные.

Как мы видим, у нас 12 переменных. Одна из них (Survived) — зависимая (целевая), остальные — независимые (признаки). Всего в датасете 891 запись, при этом в нескольких переменных есть пропуски.

Ниже приведено короткое описание каждой из переменных:

  • PassengerId — идентификатор пассажира
  • Survived — погиб (0) или выжил (1)
  • Pclass — класс билета: первый (1), второй (2) или третий (3)
  • Name — имя пассажира
  • Sex — пол
  • Age — возраст
  • SibSp — количество братьев и сестер или супругов (siblings and spouses) на борту
  • Parch — количество родителей и детей (parents and children) на борту
  • Ticket — номер билета
  • Fare — стоимость билета
  • Cabin — номер каюты
  • Embarked — порт посадки (C — Шербур; Q — Квинстаун; S — Саутгемптон)

Проведем несложный визуальный анализ данных.

У нас есть несколько потенциально значимых категориальных переменных, целевая переменная — тоже категориальная. В этом случае удобно использовать столбчатую диаграмму (bar chart), где каждый столбец также разбит на категории. В библиотеке seaborn такую диаграмму можно построить с помощью функции countplot().

количество выживших среди пассажиров первого, второго и третьего классов

Мы видим, что погибших пассажиров в третьем классе гораздо больше, чем выживших. При этом в первом классе больше выживших, чем погибших. Очевидно класс билета имеет значение.

количество выживших среди мужчин и женщин

Большинство мужчик погибло. Большая часть женщин выжила. Пол также значим для построения прогноза.

Пропущенные значения

Посмотрим, что можно сделать с пропущенными значениями (missing values).

Больше всего пропущенных значений в переменной Cabin. Они также есть в переменных Age и Embarked.

В данном случае мы применили метод .fillna(), то есть «заполнить пропуски», к столбцу Age (через train['Age']) и заполнили пропуски средним значением этого же столбца через train['Age'].mean().

Более подробно с преобразованием датафреймов мы познакомимся на курсе анализа и обработки данных. На данном этапе важно просто понимать логику нашей работы.

Посмотрим на результат.

Категориальные переменные

Теперь нужно поработать с категориальными переменными (categorical variable). Как мы помним, модель не сможет подобрать веса, если значения выражены словами (например, male и female в переменной Sex или C, Q, S в переменной Embarked).

Кроме того, даже когда категория выражена числами, иногда мы все равно не можем оставить ее без изменения. Например, если не трогать переменную Pclass, то модель воспримет классы 1, 2 и 3 как количественную переменную (как если бы это была цена или возраст), а не как категорию.

И в первом, и во втором случае к переменным нужно применить one-hot encoding. Мы уже познакомились с этим методом, когда разбирали нейронные сети. В библиотеке Pandas есть метод .get_dummies(), который как раз и выполнит необходимые преобразования.

В статистике, dummy variable или вспомогательная переменная — это переменная, которая принимает значения 0 или 1 в зависимости от наличия определенного признака.

Применим этот метод на практике.

one-hot encoding без удаления первого столбца

Первый пассажир — мужчина (в колонке male стоит 1), второй и третий — женщина. Помимо этого, если присмотреться, то станет очевидно, что мы можем обойтись только одним столбцом. В частности, в столбце male уже содержится достаточно информации о поле (если 1 — мужчина, если 0 — женщина). Это значит, что первый столбец можно удалить.

one-hot encoding с удалением первого столбца

Сделаем то же самое для переменных Pclass и Embarked.

Еще раз замечу, что переменную Survived трогать не надо. Она уже выражена через 0 и 1.

Присоединим новые (закодированные) переменные к исходному датафрейму train. Для этого используем функцию .concat().

Отбор признаков

Теперь давайте отберем те переменные (feature selection), которые мы будем использовать в модели.

  • В первую очередь, удалим исходные (до применения one-hot encoding) переменные Sex, Pclass и Embarked;
  • Кроме того, переменные PassengerId, Name и Ticket вряд ли скажут что-то определенное о шансах на выживание пассажира, удалим и их.
отбор признаков

Как вы видите, теперь все переменные либо количественные (Age, SibSp, Parch, Fare), либо категориальные и выражены через 0 и 1.

Нормализация данных

На занятиях по классификации и кластеризации мы уже говорили о важности приведения количественных переменных к одному масштабу. В противном случае модель может придать неоправданно большое значение признаку с большим масштабом.

масштабирование признаков

Остается небольшой технический момент. Переменные 2 и 3 (второй и третий класс) выражены числами, а не строками (их выдает отсутствие кавычек в коде ниже). Так быть не должно.

Преобразуем эти переменные в тип str через функцию map().

Шаг 2. Разделение обучающей выборки

Разделим обучающую выборку на признаки и целевую переменную.

разделение на обучающую и тестовую выборки

Шаг 3. Обучение модели логистической регрессии

Воспользуемся моделью логистической регрессии из библиотеки sklearn и передадим ей обучающую выборку.

Остается сделать прогноз и оценить качество модели. При этом обратите внимание, что в тестовых данных отсутствует целевая переменная (почему это так, расскажу ниже), поэтому чтобы иметь хоть какое-то представление о качестве модели, нам необходимо вначале использовать обучающую выборку для построения прогноза.

Теперь мы можем сравнить прогнозные значения с фактическими. Построим матрицу ошибок (confusion matrix).

матрица ошибок модели логистической регрессии

Для удобства интерпретации добавим подписи.

матрица ошибок с подписями

Также давайте посмотрим на метрику accuracy. Она показывает долю правильно предсказанных значений. То есть мы берем тех, кого верно предсказали как погибших (true negative, TN, таких было 478), и тех, кого верно предсказали как выживших (true positive, TP, 237), и делим на общее число прогнозов.

На обучающей выборке наша модель показала результат в 80,4%. При этом только на тестовой выборке мы можем объективно оценить качество нашего алгоритма.

Шаг 4. Построение прогноза на тестовых данных

Посмотрим на тестовые данные.

Взглянув на сводку по тестовым данным, становится заметна одна сложность. Мы обучили модель на обработанных данных. В частности, мы заполнили пропуски, закодировали категориальные переменные и убрали лишние признаки. Кроме того, мы масштабировали количественные переменные и превратили названия столбцов в строки.

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

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

one-hot encoding и отбор признаков тестовых данных

Теперь нужно масштабировать количественные переменные. Для этого мы будем использовать те параметры (среднее арифметическое и СКО), которые мы получили при обработке обучающей выборки. Так мы сохраним единообразие изменений и избежим утечки данных (data leakage).

масштабирование тестовых данных

Остается превратить название столбцов в строки.

И сделать прогноз на тестовой выборке.

На выходе мы получаем массив с прогнозами.

Этап 4. Сохранение результата в новом файле на сервере

Теперь, когда прогноз готов, мы можем сформировать новый файл, назовем его result.csv, в котором будет содержаться id пассажира и результат, погиб или нет. Приведу пример того, что мы хотим получить.

образец файла с результатом

Перед созданием нужного нам файла (1) соберем данные в новый датафрейм.

датафрейм с результатом

И (2) создадим новый файл.

Новый файл появится в «Сессионном хранилище».

файл result.csv в сессионном хранилище

Этап 5. Скачивание обратно на жесткий диск

После этого мы можем скачать файл на жесткий диск.

Вот что у нас получилось.

файл result.csv на жестком диске

Про соревнования на Kaggle

Вы вероятно заметили, что мы так и не узнали насколько хорош наш алгоритм на тестовой выборке. У нас просто нет тестовой целевой переменной (y_test).

Дело в том, что эти данные взяты с платформы, которая называется Kaggle⧉.

платформа Kaggle

На этой платформе проводятся соревнования по машинному обучению. Участники получают данные, строят модели и затем подгружают свой результат. Kaggle его оценивает и тот или те, чья модель наиболее точна — выигрывают.

Соревнование «Титаник»

«Титаник» — одно из стартовых соревнований Kaggle для новичков. Предлагаю прямо сейчас в нем поучавствовать. На странице соревнования⧉, после того как вы зарегистрировались на сайте и присоединились к самому соревнованию, у вас появится возможность подгрузить файл с результатом.

Для этого зайдите на вкладку Submit Predictions⧉, (1) подгрузите файл result.csv с локального компьютера и (2) нажмите кнопку Make Submission.

подгрузка результата по датасету "Титаник" на Kaggle

Платформа сама рассчитает accuracy вашего прогноза «на тесте» (Score). В нашем случае accuracy составляет 0,77033 или 77,03%. Чуть хуже, чем показатель «на трейне» (напомню, там было 80,4%).

accuracy score прогноза

Нажав на Jump to your position on the leaderboard, система сообщит вам ваше место в рейтинге участников (лидерборде).

место в лидерборде

Мы с вами оказались на 9512-ом месте из примерно 14500 участников. Для первого раза это хороший результат.

Подведем итог

Первая часть занятия была посвящена работе с внешними файлами. Мы научились:

  1. Подгружать внешний файл в сессионное хранилище
  2. Читать этот файл внутри ноутбука
  3. Обучать модель «на трейне» и делать прогноз на тестовых данных
  4. Подгружать прогноз в сессионное хранилище
  5. Скачивать его на жесткий диск

Во второй части мы приняли участие в соревновании «Титаник» на платформе Kaggle. Подгрузив прогноз, платформа сообщила нам accuracy нашей модели «на тесте» и наше место в лидерборде.

Вопросы для закрепления

Как вы считаете, что предпочтительнее использовать, функцию open() или конструкцию with open()?

Посмотреть правильный ответ

Какие данные мы подгрузили на платформу Kaggle?

Посмотреть правильный ответ

В следующий раз мы подробнее изучим возможности Питона по работе с датой и временем.