Как решить таймаут Google Colab и Drive
Если вы новичок в работе с миллионами файлов для анализа данных с помощью Google Colab и Google Drive, у меня есть несколько новостей: речь идет не только об алгоритмах, наборах для обучения / разработки / тестирования или настройке параметров. Управление системными файлами очень важно для успеха вашего проекта в области науки о данных.
Я кое-что узнал об этом на собственном горьком опыте, когда работал над диссертацией.
Моя диссертация
Моя диссертация посвящена генерации естественного языка на основе аудиофайлов, для этого у меня есть 1,6 миллиона файлов.
Кроме того, я хочу использовать графический процессор Google Colab для обучения моей модели и Google Drive для хранения моих данных.
Что я сделал первым
Я только что загрузил все свои данные в папку «Data» на моем Google Диске, используя следующую функцию:
def uploader(file, filename): file1 = drive.CreateFile({"parents": [{"kind": "drive#fileLink", "id": ‘<my_folder_id>’ }],"title": filename}) file1.SetContentFile(file) file1.Upload()
Затем этот «цикл for» загрузил каждый файл на Google Диск.
for i in range(0,len(my_files)): file=path+my_files[i] filename=my_files[i] uploader(file, filename)
Что я нашел
Возникает ошибка тайм-аута чтения, подобная следующей:
Это происходит, когда у вас есть тысячи файлов в вашем каталоге, и если вы не можете прочитать свои данные, вы не сможете обучить свою модель, и ваш проект завершится ошибкой.
Теоретическое решение
Мой научный руководитель порекомендовал мне создать подпапки, чтобы не повредить файловую систему и избежать проблемы с тайм-аутом в Google Colab, когда я пытаюсь их прочитать.
Как это работает?
Представьте, что у вас есть 3 файла с именами:
- ааб
- аба
- баа
Идея состоит в том, чтобы создавать подпапки на основе первой буквы их имен, затем второй буквы и так далее.
Помните, что моя основная папка - это «Данные», у меня есть три файла, и в этом случае я создам два уровня вложенных папок.
Первый уровень вложенных папок:
Первый уровень основан на первой букве каждого файла, учитывая, что у меня есть файлы, в моем каталоге будет два подкаталога.
Данные /
├── a
├── b
Второй уровень вложенных папок:
Второй уровень основан на второй букве каждого файла, учитывая файлы, которые у меня есть, теперь каждая из моих подпапок будет иметь:
a/
├── a
├── b
b/
├── a
Таким образом, наши окончательные каталоги для чтения каждого из наших файлов:
Кодовое решение
Вспомогательные функции
«Листа» на самом деле помощник помощников. Это полезно для получения имен вложенных папок (и файлов) и их идентификаторов. Следуя примеру, если мы применим его к «… / Data», мы получим имена подпапок (a и b) и их идентификаторы.
def lista(file_list): title=[] idx=[] for file in file_list: title.append(file['title']) idx.append(file['id']) dictionary = dict(zip(title, idx)) return title,dictionary
«Проверка» сообщает, сколько вложенных папок должна создать функция «Основная». Кроме того, он возвращает «helper_path», который является идентификатором уже созданного более глубокого подкаталога.
def verification(file_list,helper): helper_path=first_path file_list_helper=file_list start_range=0 title,dictionary=lista(file_list_helper) letter=helper[0] if letter in title: helper_path = dictionary[letter] file_list_helper = drive.ListFile({'q': "'"+helper_path+"'"+" in parents and trashed=false"}).GetList() start_range+=1 for i in range(1,tree_depth): title,dictionary=lista(file_list_helper) letter=helper[i] if letter in title: helper_path = dictionary[letter] file_list_helper = drive.ListFile({'q': "'"+helper_path+"'"+" in parents and trashed=false"}).GetList() start_range+=1 else: break return start_range,helper_path
«Подкаталог» создает папки подкаталога и принимает три параметра: «Helper_path», «helper» и «i».
«Helper_path» - это идентификатор последней созданной подпапки, «i» - это i из «цикла for», а буква в позиции i станет именем подпапки, которая будет создана.
def subdirectory(path,helper,i): letter=helper[i] sd = drive.CreateFile({'title':letter, "parents": [{"id": path}], "mimeType": "application/vnd.google-apps.folder"}) sd.Upload() file_list = drive.ListFile({'q': "'"+path+"'"+" in parents and trashed=false"}).GetList() title,dictionary=lista(file_list) if letter in title: return_path = dictionary[letter] return return_path
Load »загружает файл на Google Диск и имеет три параметра:« last_path »,« file »и« filename ». «Last_path» - это идентификатор целевой папки, и он нужен вам, чтобы поместить файл в нужное место. «Имя файла» - это имя, которое файл появится в папке назначения. «Файл» - это каталог вашего файла на жестком диске, куда идет код, чтобы взять файл для его загрузки. Кроме того, эта функция проверяет, существует ли уже файл в папке назначения, и избегает загрузки одного и того же файла дважды.
def load(last_path,helper_2): file_h = drive.CreateFile({"parents": [{"kind": "drive#fileLink", "id": last_path}],"title": helper_2}) destiny=drive.ListFile({'q': "'"+last_path+"'"+" in parents and trashed=false"}).GetList() title,_=lista(destiny) if helper_2 not in title: file_h.SetContentFile(file) file_h.Upload()
Функция main использует всех этих помощников для достижения этой цели следующим образом:
- Удалите пробелы и строчные заглавные буквы, если они существуют. Если у вас есть файл с названием «День из жизни», цель состоит в том, чтобы получить «adayinthelife», чтобы избежать пробелов и иметь подпапки, такие как «A» или «a».
- Загрузите словарь, в котором мы храним идентификаторы назначения папок. Цель состоит в том, чтобы ускорить процесс, если папка назначения уже создана. Если целевая папка существует, код пропускает шаг 3 и выполняет шаг 4.
- Мы определяем, сколько новых вложенных папок нам следует создать. Например, если у нас есть новый файл с именем «aca», а у нас уже есть «… Data / a», нам нужно создать только «c».
- Загружаем наши данные.
- Мы добавляем новый идентификатор папки назначения в наш словарь (на случай, если мы только что создали его).
def main(file,filename,first_path,tree_depth): helper_2=filename helper=helper_2.strip() helper=helper.lower() helper=helper.replace(" ", "") direc_dic=np.load('directorio_dict.npy',allow_pickle='TRUE').item() for i in range(tree_depth): if i==0: direc=helper[i] else: direc=direc+helper[i] if direc in direc_dic: helper_path=direc_dic[direc] load(helper_path,helper_2) else: file_list = drive.ListFile({'q': "'"+first_path+"'"+" in parents and trashed=false"}).GetList() start_range, helper_path=verification(file_list,helper) if start_range<tree_depth: for i in range(start_range,tree_depth): helper_path=subdirectory(helper_path,helper,i) load(helper_path,helper_2) direc_dic[direc]=helper_path np.save('directorio_dict.npy', direc_dic) if start_range==tree_depth: load(helper_path,helper_2) direc_dic[direc]=helper_path np.save('directorio_dict.npy', direc_dic)
Последний шаг
Лично я предпочитаю запускать Организатор из другого блокнота Jupyter. Этот дополнительный блокнот под названием «Massive_uploader» полезен для входа в вашу учетную запись Google, настройки Организатора и создания «цикла for» для загрузки всех нужных файлов.
Сначала убедитесь, что вы включили API Google Диска, а затем выполните следующий блок кода. В вашем браузере откроется новая вкладка.
from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive import os g_login = GoogleAuth() g_login.LocalWebserverAuth() drive = GoogleDrive(g_login)
Затем пора определить, сколько подуровней вы хотите с помощью tree_depth и идентификатора папки, в которую вы будете загружать свои данные на свой Google Диск с помощью first_path.
import numpy as np import re tree_depth=3 first_path='your_main_folder_id'
Вы можете получить id (first_path) из URL. Представьте, что вы уже находитесь в папке, в которой хотите создать подпапки и хранить все свои данные. Идентификатор (first_path) - это номер после последнего «/».
Чтобы получить данные, которые вы хотите загрузить, сначала вы определяете путь. Путь - это место, где вы храните свои данные локально. Например, в моем случае это «/ home / facudeza / tesis». Затем мы извлекаем все файлы, которые есть в пути.
path='directory_where_you_have_your_data_on_your_hard_disk' my_files=os.listdir(path)
Затем убедитесь, что вы загрузили блокнот Organizer в свой каталог Jupyter и вызываете его.
%run ./Organizer.ipynb
Наконец, вы выполняете цикл загрузки файлов.
for i in range(0,len(my_files)): file=path+my_files[i] filename=my_files[i] main(file,filename,first_path,tree_depth)
Вы можете ускорить процесс, создавая копии Massive_uploader и выполняя их параллельно, но будьте осторожны, чтобы не превысить вашу квоту API.
Заключение
Таким образом я понял, как справиться с этой проблемой и облегчить чтение моих файлов из Google Colab.
Вы можете скачать Органайзер и Massive_uploader,
Если у вас есть совет, рекомендация или комментарий, мы будем рады их приветствовать.
Спасибо за чтение.
Вам понравился этот пост?
Порекомендуйте, поделившись им в социальных сетях
Хотите вместе со мной читать и изучать науку о данных?
Подписывайтесь на меня на Medium