Hub documentation
Pandas
Pandas
Pandas๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ Python ๋ฐ์ดํฐ ๋ถ์ ํดํท์
๋๋ค.
์๊ฒฉ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ฐ๋ ๋ฐ fsspec์ ์ฌ์ฉํ๋ฏ๋ก, Hugging Face ๊ฒฝ๋ก(hf://)๋ฅผ ์ฌ์ฉํ์ฌ Hub์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ธ ์ ์์ต๋๋ค.
DataFrame ๋ก๋
๋ก์ปฌ ํ์ผ ๋๋ Hugging Face Datasets์ ๊ฐ์ ์๊ฒฉ ์ ์ฅ์์์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค. Pandas๋ CSV, JSON, Parquet ๋ฑ ๋ค์ํ ํฌ๋งท์ ์ง์ํฉ๋๋ค:
>>> import pandas as pd
>>> df = pd.read_csv("path/to/data.csv")Hugging Face์์ ํ์ผ์ ๋ก๋ํ๋ ค๋ฉด ๊ฒฝ๋ก๊ฐ hf://๋ก ์์ํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, stanfordnlp/imdb ๋ฐ์ดํฐ์
์ ์ฅ์์ ๊ฒฝ๋ก๋ hf://datasets/stanfordnlp/imdb์
๋๋ค. Hugging Face์ ๋ฐ์ดํฐ์
์๋ ์ฌ๋ฌ Parquet ํ์ผ์ด ํฌํจ๋์ด ์์ต๋๋ค. Parquet ํ์ผ ํ์์ ๋ฐ์ดํฐํ๋ ์์ ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ง๋ค๊ณ , ๋ฐ์ดํฐ ๋ถ์ ์ธ์ด ๊ฐ ๋ฐ์ดํฐ ๊ณต์ ๋ฅผ ์ฝ๊ฒ ํ๋๋ก ์ค๊ณ๋์์ต๋๋ค. plain_text/train-00000-of-00001.parquet ํ์ผ์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
>>> import pandas as pd
>>> df = pd.read_parquet("hf://datasets/stanfordnlp/imdb/plain_text/train-00000-of-00001.parquet")
>>> df
text label
0 I rented I AM CURIOUS-YELLOW from my video sto... 0
1 "I Am Curious: Yellow" is a risible and preten... 0
2 If only to avoid making this type of film in t... 0
3 This film was probably inspired by Godard's Ma... 0
4 Oh, brother...after hearing about this ridicul... 0
... ... ...
24995 A hit at the time but now better categorised a... 1
24996 I love this movie like no other. Another time ... 1
24997 This film and it's sequel Barry Mckenzie holds... 1
24998 'The Adventures Of Barry McKenzie' started lif... 1
24999 The story centers around Barry McKenzie who mu... 1Hugging Face ๊ฒฝ๋ก ๋ฐ ๊ตฌํ ๋ฐฉ์์ ๋ํ ์์ธํ ๋ด์ฉ์ HfFileSystem์ ๋ํ ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋์ผํ
hf://๊ฒฝ๋ก๋ Storage Buckets์์ ์ฌ์ฉํ ์ ์์ต๋๋ค:>>> df = pd.read_parquet("hf://buckets/username/my-bucket/data.parquet") >>> df.to_parquet("hf://buckets/username/my-bucket/output.parquet")
DataFrame ์ ์ฅ
to_csv/to_json/to_parquet๋ฅผ ์ฌ์ฉํ์ฌ pandas DataFrame์ ๋ก์ปฌ ํ์ผ ๋๋ Hugging Face์ ์ง์ ์ ์ฅํ ์ ์์ต๋๋ค.
Hugging Face์ DataFrames๋ฅผ ์ ์ฅํ๋ ค๋ฉด ๋จผ์ Hugging Face ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
hf auth login๊ทธ ํ ๋ฐ์ดํฐ์ ์ ์ฅ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
from huggingface_hub import HfApi
HfApi().create_repo(repo_id="username/my_dataset", repo_type="dataset")๋ง์ง๋ง์ผ๋ก, Pandas์์ Hugging Face ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
import pandas as pd
df.to_parquet("hf://datasets/username/my_dataset/imdb.parquet")
# or write in separate files if the dataset has train/validation/test splits
df_train.to_parquet("hf://datasets/username/my_dataset/train.parquet")
df_valid.to_parquet("hf://datasets/username/my_dataset/validation.parquet")
df_test .to_parquet("hf://datasets/username/my_dataset/test.parquet")Hugging Face์ Parquet ํ์ผ์ ์ ์ฅ ํจ์จ์ฑ์ ๋์ด๊ณ , ๋ค์ด๋ก๋ ๋ฐ ์ ๋ก๋๋ฅผ ๊ฐ์ํํ๋ฉฐ, ํจ์จ์ ์ธ ๋ฐ์ดํฐ์ ์คํธ๋ฆฌ๋ฐ ๋ฐ ํธ์ง์ ๊ฐ๋ฅํ๋๋ก ์ต์ ํ๋์ด ์์ต๋๋ค:
- Parquet Content Defined Chunking์ Hugging Face์ ์คํ ๋ฆฌ์ง ๋ฐฑ์๋์ธ Xet์ ์ต์ ํ๋ Parquet์ ๋๋ค. ์ฒญํฌ ๊ธฐ๋ฐ ์ค๋ณต ์ ๊ฑฐ๋ฅผ ํตํด ์ ๋ก๋์ ๋ค์ด๋ก๋๋ฅผ ๊ฐ์ํํ๋ฉฐ, ํจ์จ์ ์ธ ํ์ผ ํธ์ง์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
- Page index๋ ์คํธ๋ฆฌ๋ฐ ์ ํํฐ๋ฅผ ๊ฐ์ํํ๊ณ , Dataset Viewer์ ๊ฐ์ ํ๊ฒฝ์์ ํจ์จ์ ์ธ ๋๋ค ์ก์ธ์ค๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
Pandas๋ ์ต์ ํ๋ Parquet ํ์ผ์ ์์ฑํ๋ ค๋ฉด ์ถ๊ฐ ์ธ์๊ฐ ํ์ํฉ๋๋ค:
import pandas as pd
df.to_parquet(
"hf://datasets/username/my_dataset/imdb.parquet",
# Optimize for Xet
use_content_defined_chunking=True,
write_page_index=True,
)use_content_defined_chunking=True๋ฅผ ์ค์ ํ์ฌ Parquet Content Defined Chunking์ ํ์ฑํํฉ๋๋ค. ์ค๋ณต ์ ๊ฑฐ ๋ฐ ํธ์ง์ ์ฌ์ฉ๋ฉ๋๋ค(pyarrow>=21.0ํ์).write_page_index=True๋ฅผ ์ค์ ํ์ฌ Parquet ๋ฉํ๋ฐ์ดํฐ์ ํ์ด์ง ์ธ๋ฑ์ค๋ฅผ ํฌํจํ๋ฉด ์คํธ๋ฆฌ๋ฐ ๋ฐ ๋๋ค ์ก์ธ์ค๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
Content defined chunking(CDC)์ Parquet writer๊ฐ ์ค๋ณต ๋ฐ์ดํฐ๊ฐ ๋์ผํ๊ฒ chunk๋๊ณ ์์ถ๋๋๋ก ๋ฐ์ดํฐ ํ์ด์ง๋ฅผ chunkingํฉ๋๋ค. CDC๊ฐ ์์ผ๋ฉด ํ์ด์ง๊ฐ ์์๋ก chunking๋๋ฏ๋ก, ์์ถ ๋๋ฌธ์ ์ค๋ณต ๋ฐ์ดํฐ๋ฅผ ๊ฐ์งํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. CDC ๋๋ถ์ ์ค๋ณต ๋ฐ์ดํฐ๊ฐ ํ ๋ฒ๋ง ์ ๋ก๋ ๋๋ ๋ค์ด๋ก๋๋๋ฏ๋ก, Hugging Face๋ก์ Parquet ์ ๋ก๋ ๋ฐ ๋ค์ด๋ก๋๊ฐ ๋ ๋นจ๋ผ์ง๋๋ค.
Xet์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ฌ๊ธฐ์์ ํ์ธํ์ธ์.
Parquet์ Xet ์ค๋ณต ์ ๊ฑฐ ํ์ฉ
์ต์ ํ๋ Parquet ํ์ผ์ ์ค๋ณต ์ ๊ฑฐ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ Content Defined Chunking์ผ๋ก ์์ฑ๋ฉ๋๋ค. ์ด๋ก ์ธํด Hugging Face์ ์ด๋ฏธ ์กด์ฌํ๋ ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ๋ค์ ์ ๋ก๋ํ ํ์๊ฐ ์์ด ์ ๋ก๋ ์๋๊ฐ ๋นจ๋ผ์ง๊ณ , I/O๋ฅผ ํฌ๊ฒ ์ ์ฝํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์ด ์ฝ๋๋ df์ ๋ด์ฉ์ ์
๋ก๋ํ ํ edited_df์ ๊ฒฝ์ฐ ๋ณ๊ฒฝ๋ ์ฒญํฌ๋ง ์
๋ก๋ํ๋ฏ๋ก ์
๋ก๋ ์๋๊ฐ ๋ ๋น ๋ฆ
๋๋ค:
import pandas as pd
df.to_parquet(
"hf://datasets/username/my_dataset/imdb.parquet",
# Optimize for Xet
use_content_defined_chunking=True,
write_page_index=True,
)
edited_df = ... # e.g. with added/modified/removed rows or columns
edited_df.to_parquet(
"hf://datasets/username/my_dataset/imdb.parquet",
# Optimize for Xet
use_content_defined_chunking=True,
write_page_index=True,
)Chunk์ ์ฝ 64kB์ด๋ฉฐ Parquet๋ ์ปฌ๋ผ๋ณ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฏ๋ก, ์ค์ ๋ก Optimized Parquet ํ์ผ์ ํธ์งํ ๋ ๋ค์๊ณผ ๊ฐ์ ์ผ์ด ๋ฐ์ํฉ๋๋ค:
- ์๋ก์ด ์ด์ ์ถ๊ฐํ๋ฉด -> ์๋ก์ด ์ด์ ์ฒญํฌ๋ง ์ ๋ก๋๋ฉ๋๋ค
- add/edit/delete a row -> ์ปฌ๋ผ๋น ํ๋์ chunk๊ฐ ์ ๋ก๋๋ฉ๋๋ค
๊ทธ๋ฆฌ๊ณ ์ด ์ธ์๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ Parquet ํธํฐ์ ์ฒญํฌ๋ ์ ๋ก๋๋ฉ๋๋ค.
์ด๋ฏธ์ง ์ฌ์ฉ
์ด๋ฏธ์ง ์ด๋ฆ ๋๋ ๊ฒฝ๋ก ํ๋๋ฅผ ํฌํจํ๋ ๋ฉํ๋ฐ์ดํฐ ํ์ผ์ด ์๋ ํด๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋ก๋ํ ์ ์์ต๋๋ค:
Example 1: Example 2:
folder/ folder/
โโโ metadata.csv โโโ metadata.csv
โโโ img000.png โโโ images
โโโ img001.png โโโ img000.png
... ...
โโโ imgNNN.png โโโ imgNNN.png์ด๋ฏธ์ง ๊ฒฝ๋ก๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ๋ณตํ ์ ์์ต๋๋ค:
import pandas as pd
folder_path = "path/to/folder/"
df = pd.read_csv(folder_path + "metadata.csv")
for image_path in (folder_path + df["file_name"]):
...๋ฐ์ดํฐ์
์ด ์ง์๋๋ ๊ตฌ์กฐ(file_name ํ๋๊ฐ ํฌํจ๋ metadata.csv ๋๋ .jsonl ํ์ผ)๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก, ์ด ๋ฐ์ดํฐ์
์ Hugging Face์ ์ ์ฅํ๋ฉด Dataset Viewer์์ Hugging Face์ ๋ฉํ๋ฐ์ดํฐ์ ์ด๋ฏธ์ง๊ฐ ๋ชจ๋ ํ์๋ฉ๋๋ค.
from huggingface_hub import HfApi
api = HfApi()
api.upload_folder(
folder_path=folder_path,
repo_id="username/my_image_dataset",
repo_type="dataset",
)์ด๋ฏธ์ง ๋ฉ์๋์ Parquet
pandas-image-methods๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฏธ์ง ์ด์ PIL.Image ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ํ ์ด๋ฏธ์ง์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ํฌํจํ๋ ๋จ์ผ Parquet ํ์ผ๋ก ๋ฐ์ดํฐ์
์ ์ ์ฅํ๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํฉ๋๋ค:
import pandas as pd
from pandas_image_methods import PILMethods
pd.api.extensions.register_series_accessor("pil")(PILMethods)
df["image"] = (folder_path + df["file_name"]).pil.open()
df.to_parquet("data.parquet")๋ชจ๋ PIL.Image ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด
df["image"] = df["image"].pil.rotate(90)Audios ์ฌ์ฉ
๋ฉํ๋ฐ์ดํฐ ํ์ผ์ ์ค๋์ค์ ์ด๋ฆ ๋๋ ๊ฒฝ๋ก์ ๋ํ ํ๋๊ฐ ํฌํจ๋ ํด๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋ก๋ํ ์ ์์ต๋๋ค:
Example 1: Example 2:
folder/ folder/
โโโ metadata.csv โโโ metadata.csv
โโโ rec000.wav โโโ audios
โโโ rec001.wav โโโ rec000.wav
... ...
โโโ recNNN.wav โโโ recNNN.wav์์ฑ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ๋ณตํ ์ ์์ต๋๋ค:
import pandas as pd
folder_path = "path/to/folder/"
df = pd.read_csv(folder_path + "metadata.csv")
for audio_path in (folder_path + df["file_name"]):
...๋ฐ์ดํฐ์
์ด ์ง์๋๋ ๊ตฌ์กฐ(file_name ํ๋๊ฐ ํฌํจ๋ metadata.csv ๋๋ .jsonl ํ์ผ)๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก Hugging Face์ ์ ์ฅํ ์ ์์ผ๋ฉฐ, Hub Dataset Viewer์์๋ ๋ฉํ๋ฐ์ดํฐ์ ์ค๋์ค๋ฅผ ๋ชจ๋ ํ์ธํ ์ ์์ต๋๋ค.
from huggingface_hub import HfApi
api = HfApi()
api.upload_folder(
folder_path=folder_path,
repo_id="username/my_audio_dataset",
repo_type="dataset",
)์ค๋์ค ๋ฉ์๋์ Parquet
pandas-audio-methods๋ฅผ ์ฌ์ฉํ๋ฉด ์ค๋์ค ์ปฌ๋ผ์ soundfile ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ํ ์ค๋์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ํฌํจํ๋ ๋จ์ผ Parquet ํ์ผ๋ก ๋ฐ์ดํฐ์
์ ์ ์ฅํ๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํฉ๋๋ค:
import pandas as pd
from pandas_audio_methods import SFMethods
pd.api.extensions.register_series_accessor("sf")(SFMethods)
df["audio"] = (folder_path + df["file_name"]).sf.open()
df.to_parquet("data.parquet")librosa์ ํจ๊ป ์ฌ์ฉํ๊ธฐ ์ฌ์์ง๋๋ค. ์๋ฅผ ๋ค์ด ๋ฆฌ์ํ๋ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
df["audio"] = [librosa.load(audio, sr=16_000) for audio in df["audio"]]
df["audio"] = df["audio"].sf.write()Transformers ์ฌ์ฉ
transformers ํ์ดํ๋ผ์ธ์ pandas DataFrame์ ์ ์ฉํ์ฌ ๋ถ๋ฅ, ํ
์คํธ ์์ฑ, ์ด๋ฏธ์ง ์์ฑ ๋ฑ์ ์์
์ ์ํํ ์ ์์ต๋๋ค.
์ด ์น์
์์๋ ์งํ ํ์์ค์ ์ํด tqdm๋ฅผ ์ฌ์ฉํ ๋ช ๊ฐ์ง ์์ ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
Pipelines๋
tqdm๊ฐ์ฒด๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ง ์์ง๋ง,x for x in tqdm(...)ํํ์ Python ์์ฑ๊ธฐ๋ฅผ ๋์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํ ์คํธ ๋ถ๋ฅ
from transformers import pipeline
from tqdm import tqdm
pipe = pipeline("text-classification", model="clapAI/modernBERT-base-multilingual-sentiment")
# Compute labels
df["label"] = [y["label"] for y in pipe(x for x in tqdm(df["text"]))]
# Compute labels and scores
df[["label", "score"]] = [(y["label"], y["score"]) for y in pipe(x for x in tqdm(df["text"]))]ํ ์คํธ ์์ฑ
from transformers import pipeline
from tqdm import tqdm
pipe = pipeline("text-generation", model="Qwen/Qwen2.5-1.5B-Instruct")
# Generate chat response
prompt = "What is the main topic of this sentence ? REPLY IN LESS THAN 3 WORDS. Sentence: '{}'"
df["output"] = [y["generated_text"][1]["content"] for y in pipe([{"role": "user", "content": prompt.format(x)}] for x in tqdm(df["text"]))]