#
필요한 데이터셋이 Hub에 없다면 어떻게 할까요?

Hugging Face Hub를 통해 데이터셋을 다운로드하는 방법은 배웠지만, Hub가 아닌 로컬 환경이나 원격 서버에 저장된 데이터로 작업해야하는 경우도 많이 있을 것입니다. 이번 섹션에서는 🤗 Datasets를 이용하여 Hugging Face Hub에 없는 데이터셋을 로딩하는 방법을 알려드리도록 하겠습니다.

##
로컬 또는 원격 데이터셋으로 작업하기

🤗 Datasets는 로컬 또는 원격 데이터셋 로딩을 다루기 위한 스크립트를 제공하며 다음과 같이 몇 가지 일반적인 데이터 형식들을 지원합니다:

Data format | Loading script | Example
--- | --- | ---
CSV & TSV | `csv` | `load_dataset("csv", data_files="my_file.csv")`
Text files | `text` | `load_dataset("text", data_files="my_file.txt")`
JSON & JSON Lines | `json` | `load_dataset("json", data_files="my_file.jsonl")`
Pickled DataFrames | `pandas` | `load_dataset("pandas", data_files="my_dataframe.pkl")`

테이블에서 볼 수 있듯이, 파일에 대한 경로를 지정하는 `data_files` 인수와 함께 `load_dataset()` 함수에 각 데이터 형식에 맞는 로딩 스크립트 유형을 지정해 주기만하면 됩니다. 지금부터 로컬 파일에서 데이터셋을 로딩을 해보는 것으로 시작해서 원격 파일로 동일한 작업을 수행하는 방법을 살펴보도록 하겠습니다.

##
로컬 데이터셋 로딩하기

이번 예제에서는 이탈리아어 질의응답 (QA) 대규모 데이터셋인 SQuAD-it를 사용하겠습니다.

훈련 및 테스트 데이터는 Github에 호스팅되어 있으므로, 간단한 `wget` 명령어를 통해 다운로드 할 수 있습니다:

    !wget https://github.com/crux82/squad-it/raw/master/SQuAD_it-train.json.gz
    !wget https://github.com/crux82/squad-it/raw/master/SQuAD_it-test.json.gz

이렇게하면 SQuAD_it-train.json.gz, SQuAD_it-test.json.gz 두 개의 압축 파일을 다운로드 받을 수 있고, `gzip` 리눅스 명령어를 통해 압축을 풀 수 있습니다:

    !gzip -dkv SQuAD_it-*.json.gz

    SQuAD_it-test.json.gz:	   87.4% -- replaced with SQuAD_it-test.json
    SQuAD_it-train.json.gz:	   82.2% -- replaced with SQuAD_it-train.json

명령어를 통해 압축 파일들이 각각 SQuAD_it-train.json, SQuAD_it-test.json 로 바뀌어 저장되어 있는 것을 볼 수 있습니다.

✎ 위 쉘 명령어에 `!`가 붙는 이유는 주피터 노트북에서 실행하고 있기 때문입니다. 터미널에서 명령어를 실행한다면 `!`를 없애주시면 됩니다.

`load_dataset()` 함수로 JSON 파일을 로딩할 때, 파일이 일반 JSON (nested dictionary와 유사)으로 형태인 지 혹은 JSON Lines (줄로 구분된 JSON)형태인 지 알아야 합니다. 많은 질의응답 데이터셋처럼, SQuAD-it 데이터셋은 `data` 필드에 텍스트가 모두 저장된 nested 포맷을 사용하며, 이는 다음과 같이 `field` 인수를 지정하여 데이터셋을 로딩할 수 있음을 의미합니다:

    from datasets import load_dataset

    squad_it_dataset = load_dataset("json", data_files="SQuAD_it-train.json", field="data")

디폴트로 로컬 파일을 로딩하면 `train` 스플릿을 가진 `DatasetDict` 객체가 생성됩니다. `squad_it_dataset` 객체를 통해 이를 확인할 수 있습니다:

    squad_it_dataset

    DatasetDict({
        train: Dataset({
            features: ['title', 'paragraphs'],
            num_rows: 442
        })
    })

이것은 `train` 스플릿에 대한 행의 수 (num_rows)와 열의 이름 (features)을 보여줍니다. 또한 다음과 같이 `train` 스플릿을 인덱싱하여 한 예제를 볼 수 있습니다:

    squad_it_dataset["train"][0]

    {
        "title": "Terremoto del Sichuan del 2008",
        "paragraphs": [
            {
                "context": "Il terremoto del Sichuan del 2008 o il terremoto...",
                "qas": [
                    {
                        "answers": [{"answer_start": 29, "text": "2008"}],
                        "id": "56cdca7862d2951400fa6826",
                        "question": "In quale anno si è verificato il terremoto nel Sichuan?",
                    },
                    ...
                ],
            },
            ...
        ],
    }

훌륭하게 첫 번째 로컬 데이터셋을 로딩했습니다! 하지만 우리가 하고 싶은 것은 `train`과 `test` 스플릿을 모두 지닌 하나의 `DatasetDict` 객체를 만들어 두 스플릿에 동시에 `Dataset.map()` 함수를 적용하는 것입니다. 이를 위해, 각 스플릿 이름을 해당 스플릿과 관련된 파일에 매핑하는 dictionary를 `data_files` 인수로 줄 수 있습니다:

    data_files = {"train": "SQuAD_it-train.json", "test": "SQuAD_it-test.json"}
    squad_it_dataset = load_dataset("json", data_files=data_files, field="data")
    squad_it_dataset

    DatasetDict({
        train: Dataset({
            features: ['title', 'paragraphs'],
            num_rows: 442
        })
        test: Dataset({
            features: ['title', 'paragraphs'],
            num_rows: 48
        })
    })

이것이 바로 우리가 원했던 것입니다. 이제 다양한 전처리 기법을 적용하여 데이터를 정리하고, 리뷰를 토큰화하는 등의 작업을 수행할 수 있습니다.

`load_dataset()` 함수의 `data_files` 인수는 매우 유연하여 하나의 파일 경로 (str), 파일 경로들의 리스트 (list) 또는 스플릿 이름을 각 파일 경로에 매핑하는 dictionary를 값으로 받을 수 있습니다. 또한 Unix 쉘에서 사용하는 규칙에 따라 지정된 패턴과 일치하는 파일들을 glob할 수도 있습니다. (예를 들어, `data_files="*.json"`와 같이 설정하면 한 폴더에 있는 모든 JSON 파일들을 하나의 스플릿으로 glob할 수 있습니다.) 자세한 내용은 🤗 Datasets documentation에서 확인할 수 있습니다.

🤗 Datasets 로딩 스크립트는 입력 파일의 자동 압축 해제를 지원하기 때문에 실제로 사용할 때는 `data_files` 인수로 압축 파일을 입력하면 `gzip` 사용을 생략할 수 있습니다.

    data_files = {"train": "SQuAD_it-train.json.gz", "test": "SQuAD_it-test.json.gz"}
    squad_it_dataset = load_dataset("json", data_files=data_files, field="data")

이는 많은 GZIP 파일들을 수동으로 압축 해제하고 싶지 않을 때 유용하며, ZIP, TAR과 같은 일반적인 포맷들도 지원하므로 `data_files`에 해당 파일을 입력해 주기만 하면 됩니다.

노트북이나 데스크탑에서 로컬 파일을 로딩하는 방법을 알아봤으므로, 이제 원격 파일을 로딩하는 방법을 살펴보겠습니다.

##
원격 데이터셋 로딩하기

만약 당신이 회사에서 데이터 과학자 또는 개발자로 일하고 있다면 분석하려는 데이터셋이 원격 서버에 저장되어 있을 가능성이 큽니다. 다행히, 원격 파일을 로딩하는 것은 로컬 파일을 로딩하는 것만큼 간단합니다! 로컬 파일 경로를 입력하는 대신, `load_dataset()`의 `data_files` 인수에 원격 파일들이 저장되어 있는 하나 또는 그 이상의 URL을 입력해주기만 하면 됩니다. 예를 들어, GitHub에서 호스팅하고 있는 SQuAD-it 데이터셋의 경우, `data_files`에 다음과 같이 SQuAD_it-*.json.gz 을 입력하면 됩니다:

    url = "https://github.com/crux82/squad-it/raw/master/"
    data_files = {
        "train": url + "SQuAD_it-train.json.gz",
        "test": url + "SQuAD_it-test.json.gz",
    }
    squad_it_dataset = load_dataset("json", data_files=data_files, field="data")

이와 같은 방법을 통해 위에서 얻은 것과 같이 `DatasetDict` 객체를 생성할 수 있으며 수동으로 파일들을 다운로드받고 압축을 푸는 작업을 생략할 수 있습니다. 지금까지 Hugging Face Hub에서 호스팅되어 있지 않은 데이터셋을 로딩하는 다양한 방법을 알아보았습니다. 이제 다뤄볼 데이터셋을 얻었으니 다양한 데이터 전처리 기법을 배워보도록 합시다.

✏️ 시도해 보세요! GitHub 또는 UCI Machine Learning Repository에서 호스팅되는 다른 데이터셋을 선택하여 위에서 배운 기술을 통해 로컬 또는 원격으로 로딩해 보시고, 추가적으로 CSV 또는 텍스트 포맷으로 저장된 데이터셋도 로딩을 시도해 보시길 바랍니다. (이 포맷들에 대한 자세한 정보는 documentation을 참조하세요.)