{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "UiO1w9dn_ZHb" }, "source": [ "# 라이브러리 설치" ] }, { "cell_type": "markdown", "metadata": { "id": "2sepsyCU_b--" }, "source": [ "- 양자화, 실행 최적화, 효율적 파인튜닝, 데이터셋 처리, 시각화 라이브러리 불러오기" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "DyzIFdONrhtC", "outputId": "1ef1c80a-92e1-45c8-b89b-5a7c8c1f3d11" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.0/76.0 MB\u001b[0m \u001b[31m25.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m411.0/411.0 kB\u001b[0m \u001b[31m23.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m491.2/491.2 kB\u001b[0m \u001b[31m31.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.5/5.5 MB\u001b[0m \u001b[31m105.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m116.3/116.3 kB\u001b[0m \u001b[31m9.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m183.9/183.9 kB\u001b[0m \u001b[31m12.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m143.5/143.5 kB\u001b[0m \u001b[31m12.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m363.4/363.4 MB\u001b[0m \u001b[31m2.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.8/13.8 MB\u001b[0m \u001b[31m80.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m24.6/24.6 MB\u001b[0m \u001b[31m79.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m883.7/883.7 kB\u001b[0m \u001b[31m45.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m664.8/664.8 MB\u001b[0m \u001b[31m1.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m211.5/211.5 MB\u001b[0m \u001b[31m9.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m56.3/56.3 MB\u001b[0m \u001b[31m35.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m127.9/127.9 MB\u001b[0m \u001b[31m8.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m207.5/207.5 MB\u001b[0m \u001b[31m9.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.1/21.1 MB\u001b[0m \u001b[31m92.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.8/194.8 kB\u001b[0m \u001b[31m18.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25h\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", "tensorflow 2.18.0 requires tensorboard<2.19,>=2.18, but you have tensorboard 2.19.0 which is incompatible.\n", "gcsfs 2025.3.0 requires fsspec==2025.3.0, but you have fsspec 2024.12.0 which is incompatible.\u001b[0m\u001b[31m\n", "\u001b[0m" ] } ], "source": [ "!pip install -q -U bitsandbytes accelerate peft datasets tensorboard" ] }, { "cell_type": "markdown", "metadata": { "id": "I15Xh4DNr1nw" }, "source": [ "# HuggingFace 로그인 및 데이터 업로드" ] }, { "cell_type": "markdown", "metadata": { "id": "MgVSOYxQ-Oi4" }, "source": [ "- 구글 드라이브를 마운트해서 데이터를 불러오는 방식이 아닌 HuggingFace에 업로드해서 다시 불러오는 방식으로 데이터 사용" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ZLbzElKyrn-r" }, "outputs": [], "source": [ "# HuggingFace hub에 업로드하기 위해 인증 토큰으로 로그인\n", "from huggingface_hub import login\n", "\n", "login(token=\"token\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Wu8rsKbIr9-N" }, "outputs": [], "source": [ "import os\n", "import shutil\n", "\n", "# 저장할 디렉토리 이름\n", "dataset_name = \"empathy_chat_couple_data\"\n", "\n", "# 디렉토리 생성\n", "if os.path.exists(dataset_name):\n", " shutil.rmtree(dataset_name)\n", "os.makedirs(dataset_name)\n", "\n", "# jsonl 파일 복사\n", "# 전처리한 파일 HuggingFace hub에 업로드\n", "shutil.copy(\"/content/converted_format.jsonl\", f\"{dataset_name}/data.jsonl\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "yE1BpErpr_Go" }, "outputs": [], "source": [ "from huggingface_hub import create_repo, upload_folder\n", "\n", "# Hugging Face에 데이터셋용 저장소 만들기\n", "create_repo(repo_id=f\"shjun/{dataset_name}\", repo_type=\"dataset\", exist_ok=True)\n", "\n", "# 디렉토리 통째로 업로드\n", "upload_folder(\n", " repo_id=f\"shjun/{dataset_name}\",\n", " folder_path=dataset_name,\n", " repo_type=\"dataset\"\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "d-YCX6nN9_dq" }, "source": [ "" ] }, { "cell_type": "markdown", "metadata": { "id": "5mxWSYaAsLfg" }, "source": [ "# HuggingFace에서 데이터셋 가져오기" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 190, "referenced_widgets": [ "f3f714a45faa410aa8fe97afbfad4bc9", "81452c23ddc74b73b00683e6e0ffd62c", "5a457b732e6f41d6bdd60d3e319e16b3", "3ec60119a667432591ff84d689498d64", "ef3bfefab1894c639c1efa361e02ad1c", "93bc3ada38bb4544a20337de5b480c80", "3997e390204e4f93ad584bc43a763092", "e3d10614ae6840b8978dfe947d52794e", "25859ea43ecd4c36ababe00bd9d9a9ee", "ea835a895f704f68a5f2632a0ab69a5e", "fb9b3e0f77724dd49226198162394de9", "c3a5b2d6e7014e6485397b1cd800b858", "ea1fc5e0e5b445cfbe8f3546014975de", "3efe0e4cfa204ff5bef1bb1460149e2e", "322b8fffe4e5498188bc56ba62ecccf4", "cfd3b1e036dc40c4ad31e15e523236e7", "98ad3eaf942348e59aea1964abd2202c", "5d4799296ede4114a5bad2648def9ca1", "cbbb14ab13854610858fadba2e4ca5c2", "afc57fb7a5264dea966c34249a91bacf", "ef23cddf9b8748c0a7722500c2af0410", "720b980a7f644059ae593129c7e8e0ed" ] }, "id": "8h-5xlBJsAwb", "outputId": "3598fb76-3221-4ed2-9323-6945dcb5225d" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.11/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n", "The secret `HF_TOKEN` does not exist in your Colab secrets.\n", "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n", "You will be able to reuse this secret in all of your notebooks.\n", "Please note that authentication is recommended but still optional to access public models or datasets.\n", " warnings.warn(\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "f3f714a45faa410aa8fe97afbfad4bc9", "version_major": 2, "version_minor": 0 }, "text/plain": [ "data.jsonl: 0%| | 0.00/12.0M [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c3a5b2d6e7014e6485397b1cd800b858", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Generating train split: 0%| | 0/3646 [00:00, ? examples/s]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from datasets import load_dataset\n", "import torch\n", "import numpy as np\n", "from transformers import AutoTokenizer , Trainer, AutoModelForCausalLM, BitsAndBytesConfig, TrainingArguments, DataCollatorForLanguageModeling\n", "from transformers import (\n", " AutoModelForCausalLM,\n", " AutoTokenizer,\n", " BitsAndBytesConfig,\n", " StoppingCriteria,\n", " StoppingCriteriaList,\n", ")\n", "\n", "from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model\n", "from huggingface_hub import login\n", "\n", "# 데이터 셋 가져오기\n", "login(token=\"token\")\n", "data = load_dataset(\"shjun/empathy_chat_couple_data\")" ] }, { "cell_type": "markdown", "metadata": { "id": "Y66opCjMCJxg" }, "source": [ "# Base 모델 불러오기 및 양자화 설정" ] }, { "cell_type": "markdown", "metadata": { "id": "HfrZmhmmBJo-" }, "source": [ "**✅양자화란?**\n", "\n", "✔ 데이터의 양자화 (Quantization)은 숫자의 정밀도를 줄여서 모델을 작고 빠르게 만드는 기술\n", "\n", "\n", "---\n", "\n", "\n", "**🎯 왜 사용?**\n", "\n", "모델이 사용하는 숫자는 보통 **32비트(부동소수점, float32)**이고 이걸 8비트 정수(int8) 같은 낮은 정밀도로 바꾸면:\n", "\n", "+ 모델 용량이 줄어들고 (→ 저장 공간 적게 차지)\n", "\n", "+ 연산 속도가 빨라지고 (→ 모바일이나 엣지에서 빠르게 동작)\n", "\n", "+ 메모리도 덜 먹어 (→ GPU 없이도 가능!)\n" ] }, { "cell_type": "markdown", "metadata": { "id": "cWJpqeUMDKbh" }, "source": [ "**✅토큰이란?**\n", "\n", "✔ 단어나 문자, 서브워드 등의 작은 단위\n", "\n", "✔ 모델이 텍스트를 처리할 수 있도록 숫자로 변환됨\n", "\n", "\n", "\n", "---\n", "\n", "\n", "**🧠 LLM 모델은 텍스트 자체를 이해하지 못한다!!**\n", "\n", "ex. \"안녕하세요. 반가워요!\"\n", "\n", "모델은 텍스트 자체를 이해하지 못하기 때문에 \"문자열(텍스트)\"이 아니라 \"숫자(벡터)\"를 받아야함\n" ] }, { "cell_type": "markdown", "metadata": { "id": "zufNg4-DDdp6" }, "source": [ "**✅EOT 토큰**\n", "\n", "- Out Of Text : 텍스트의 끝을 의미하는 특수 토큰\n", "- 끝맺음 토큰이라고도 함\n", "\n", "✔ LLM 모델은 입력 텍스트가 어디서 끝났는지 알아야 하는데 그걸 알려주는 게 EOT 토큰\n", "\n", "✔사람이 보기엔 문장이 끝나면 그냥 끝이지만, 모델은 끝을 명확히 알려줘 함!!\n", "\n", "\n", "\n", "---\n", "\n", "\n", "**📌 어떤 역할??**\n", "\n", "\n", "- 학습할 때\n", "\n", "- 예측을 멈출 때\n", "\n", "- 대화가 끝났음을 나타낼 때" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 401, "referenced_widgets": [ "dc5eb7010fe24d5e82d51f610249f8d7", "3212e62af07c4fa390360f8fa72cd54e", "95961511a55d4818b74ab8e12bc668b6", "f5439c9c32c946898f19d7c1bc19416c", "01e4cc1c63684d4b97481c374a085dd0", "725f1cbd924645889fcb8a0861e1194d", "9c385b23f48d4bffb992cc0b9ee809ee", "fc82ef14c38d4213b0ec497bfe268e2b", "21f15712ddaa4dc58ba7c37861982a5c", "80c46fe5375e43fa914599e4000078a2", "c0ac2030348d4d41996a8ab664da4d7f", "5ef29f021d634406b9611a155a38379a", "6a0c2405fb414fa49a11c8dbe1d2eeec", "4608d04182ed4031ae659463c679de95", "b5dbd063c27c48b6adfdae7d1905fe1e", "21c10f2faab94549872b4dc1c11bf9b0", "2b7ebcd9886949f8ac14d4cc1dffc869", "c3d9d6f97517414aad9014f394f0e008", "57fb2af45d854a009a12a2b3f7844812", "cf14d5a8ed274e99974430209fcbe20d", "ab3227ea4bbd4cf2abe65bd7c17992a3", "b60dff995f99427c9546a7f0fcae40de", "1b54e4aa9c50439d8c7587b94397b9d9", "5a45a189833346d4af458e3a61d55c56", "2616a9c204c5429882759602a913c4bb", "45117852ed43427fb1a62c2e7c21a45b", "6a3690e81eb940c7821a62136bd6c964", "56b4d6c6d9ad4894b9067467efc9bd34", "94bc8058eae24902a17265ed25522652", "c9e009e6fee9480dac2629f22a385ac6", "65a931bb2d924c3389c0b4222347156e", "eac57bd188384cc3a3da8f4050bdba66", "653a776fb41f4c1cb1a1bc9dba6eb11b", "77aba6186adf4ad6bd1d56c1539c8bf7", "52c43ff1cd7b446a9d5d0cc9bc7429d9", "e0c9a392a29f43e9982de129ca46b8d0", "889e5d7bbece453b99adbd0f57ebc606", "7db20b29ef3641699abd74cede1b8b52", "3377c39437d840f0837c36c12d175b81", "d55d2376517f467d92d614d533d01008", "205dea4bc6d744f89bcc8416ed1b6ea2", "cbbef97fc2af4364a1d52b9f9905a64d", "5b8afd0858e6433b852bbb758f621999", "13e4db4f528a4fabb4d9ddc37aa841ee", "58a48f080f064bfb8ad9ecd20fed3c70", "3ba750a2d8bc47fea21f3c18d75ae1c2", "dd1eaf00c752414dbe00d6b00f2a4621", "7cdfeaf9ada84f9f867aac9544fa082b", "ee6869afaa144bb6b184e2d0888f7bd2", "1947383a15f4491b9df49857bd8a31c3", "2e29877cd0734c07beff351a720c17b7", "e76d4bcbcfb446f0b42d9d78e69d53a6", "c5d9a3d916c6438fb163ebe31bb899a1", "98e8320b289740a3b6c7a4b9090c0e59", "5d3c92311ba6490bbdf0a4829ddcce07", "fda6ad4f681d47aab1a0dc7d2105769c", "ed4c1b94db234d5f90415651bca4adc4", "797c6c9c0cde4053be3fd3e18989f718", "639f2e267dbe40148d2658bf758b4100", "7fc1fb0218514aaf9964477ed949fa67", "7a97f967e45e466396073bd0cf10b2a2", "da1fcd153f824860adff9533490e9aee", "93739852967146b391e50dd1331674a0", "1091794827e54e7eb2746c9b19c148fa", "6938216bebc24fb8ba93be82211c44a7", "08ba70e8ed6848288269f027d489d8d4", "d05de0b832f54e1b856857cb2008cc27", "2cd23df310ea4adc84cfeed005dbda60", "33b7db8f6d284dfeaba460adc340c063", "0b02eb5bb49d4e4482c4d169aaace251", "e6dc355a3d084939a567c795af822aef", "c1e55d1968b04ce5bba12ba1fd22558e", "aa807adc22d64a968cb5e57a0ef4266d", "d9d477b5126d45bc913fd01b10a0e2e0", "3c4336bad523449185f4aa1f3adee59c", "16bb7bfd3dcf49c8970b1423843a200e", "73a4493a3afa42eb90e5163b48850bdd", "08b0226720aa4573968d560a6392146d", "fef5624607de47e28f84a9117724c2fa", "fc820744294e446e8239af4e08f14e33", "963e09cc3e02423a828f398b63f7fdcf", "e7ffa4a3b59d415f9c1b946bedd6164b", "7c08b6ccf6184b0999fb0bb765524d94", "34ebea90512b43039a83f24ca6df48fd", "df33b3ff2aac4f0dac12fbbdbd2ff234", "c3768da45ee641dab2278c3ceae61e2e", "89b5691fe33a407086215bdab47beaf9", "629269cc0fc845659ed3b7eb1fdacddc", "b2ea975460e349cfb93f7807541cbe81", "d79d3133516046c284d9419f128944eb", "c0ed958fb92a4ae0a4e12d4d12a5aafc", "8fbf7aa680224b89b9c75be285e8e06d", "29f4ca4008da4c89ba74d14470134622", "388ed02965ae484ba2763785a2446f84", "9d6a98a0b0264523a181c3b2048552ac", "9a6f7f54937940bebd5829846d221187", "edd417d9977443e99ce15b47849ed966", "6efc044155984cf192a5460ce417b045", "36562f0d6482449ab55b66c48005b13f", "84a100f579cd4ff9b74ec3d69ed3d307", "efcc96d22da046b39aa6d6ff9c372d8f", "1e65c5ab056f41c29dab9b4497d44560", "c707be53998c4675b320efcaae14641a", "920a5d49c6f746989a10a8f6bb7f8e68", "750da6d6f5a14be3a4d57823d05d7ca2", "f77cd0eefc074055b9a4ca2c9b1fc27d", "54c6b1cf33884e5b92fa4ee0ef11b1d7", "2c4051f6d24b4531bf4bb09d50d4549c", "c82dee8c2f9d46d48ec1c500183841d1", "5603f27b7dca47bf962b858638ce771a", "cc710293d9734f3c88bcb950a3bc7024", "aca7f080e3684dbb991602f6812fc795", "796f0510fdec4ff48063ca25ccb2ebd2", "ba4a1a25d2ed48289b7d6bb446ae54cf", "dfa314ea78964ae293bfc74fcfe60ea0", "12b2dcea0d034941b980f461a2373888", "22ad4814f06b4481a5be906d076bd4ac", "5056f6c65fd64dbd9f1c6ca88eca5d90", "477190c132c24f34885cc7418fbcf1fa", "7615de990ac14bc4a3d124de841a97b5", "1ec0200b9b374d1587bc69d475c698e3", "f45a350ecc014acca32989742d019034", "5cd59e515dac46428fc1e16e544849af", "cf899890d5484ddbb97cfa72b279417f", "7dc90ffd0e494cc1acf0a9fd96da3637", "365ab25113dd4654acf17db7bb3fac13", "644c747afcac4384a34443fb88672b97", "2c3698adfc8a4e55a9b9e5380ad003ed", "87b92295a9864aba9fb322298a12ccbf", "99f30198f6e34efabd4e689c75f1e55d", "28e61215cb8046c6b5606b73c915a19c", "77b7261b00944d78a60e9a8d0e7b378d" ] }, "id": "pOBwmwyetChq", "outputId": "fb0e6b5a-23a8-49a6-e463-2cdc9381e67e" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "dc5eb7010fe24d5e82d51f610249f8d7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "tokenizer_config.json: 0%| | 0.00/1.86k [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "5ef29f021d634406b9611a155a38379a", "version_major": 2, "version_minor": 0 }, "text/plain": [ "tokenizer.json: 0%| | 0.00/2.18M [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "1b54e4aa9c50439d8c7587b94397b9d9", "version_major": 2, "version_minor": 0 }, "text/plain": [ "special_tokens_map.json: 0%| | 0.00/557 [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "77aba6186adf4ad6bd1d56c1539c8bf7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "config.json: 0%| | 0.00/695 [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "58a48f080f064bfb8ad9ecd20fed3c70", "version_major": 2, "version_minor": 0 }, "text/plain": [ "model.safetensors.index.json: 0%| | 0.00/35.8k [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "fda6ad4f681d47aab1a0dc7d2105769c", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Fetching 5 files: 0%| | 0/5 [00:00, ?it/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d05de0b832f54e1b856857cb2008cc27", "version_major": 2, "version_minor": 0 }, "text/plain": [ "model-00001-of-00005.safetensors: 0%| | 0.00/4.90G [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "08b0226720aa4573968d560a6392146d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "model-00002-of-00005.safetensors: 0%| | 0.00/4.92G [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b2ea975460e349cfb93f7807541cbe81", "version_major": 2, "version_minor": 0 }, "text/plain": [ "model-00003-of-00005.safetensors: 0%| | 0.00/5.00G [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "84a100f579cd4ff9b74ec3d69ed3d307", "version_major": 2, "version_minor": 0 }, "text/plain": [ "model-00005-of-00005.safetensors: 0%| | 0.00/1.88G [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "cc710293d9734f3c88bcb950a3bc7024", "version_major": 2, "version_minor": 0 }, "text/plain": [ "model-00004-of-00005.safetensors: 0%| | 0.00/4.92G [00:00, ?B/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "f45a350ecc014acca32989742d019034", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Loading checkpoint shards: 0%| | 0/5 [00:00, ?it/s]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# 선정 모델\n", "model_id = \"yanolja/EEVE-Korean-10.8B-v1.0\"\n", "\n", "#LoRA와 어울리는 양자화 설정\n", "bnb_config = BitsAndBytesConfig(\n", " load_in_4bit=True,\n", " bnb_4bit_use_double_quant=True,\n", " bnb_4bit_quant_type=\"nf4\",\n", " bnb_4bit_compute_dtype=torch.bfloat16\n", ")\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(model_id)\n", "model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=bnb_config, device_map={\"\":0})\n", "\n", "# 문장의 끝을 나타내는 토큰(End Of Text)\n", "EOT_TOKEN = tokenizer.eos_token" ] }, { "cell_type": "markdown", "metadata": { "id": "WLXZSW4TIO8L" }, "source": [ "# 학습 데이터 확인 및 전처리" ] }, { "cell_type": "markdown", "metadata": { "id": "WJR2qS_EJhyC" }, "source": [ "- 각 대화를 역할별로 자연스럽게 포맷팅하고 결과적으로 하나의 학습 가능한 text 필드로 생성\n", "- 이 데이터 전처리로 역할별 말하기와 끝맺음 토큰 같이 대화구조를 학습할 수 있음" ] }, { "cell_type": "markdown", "metadata": { "id": "5m0WepVNCdEa" }, "source": [ "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "gVTaQiUytKsK", "outputId": "94f68c4e-e94a-4528-a350-a78dd84901ab" }, "outputs": [ { "data": { "text/plain": [ "{'id': 3645,\n", " 'conversations': [{'role': 'speaker', 'text': '자기야, 나 너무 슬퍼서 무기력해.'},\n", " {'role': 'listener', 'text': '무슨 일 있었어 ?'},\n", " {'role': 'speaker',\n", " 'text': '새로 산 운동화를 신고 나갔는데 소나기가 와서 흙탕물이 튀었어. 새 신발이 금방 더러워져서 속상해.'},\n", " {'role': 'listener',\n", " 'text': '아이고, 정말 속상할 수밖에 없는 상황이구나. 새 신발 신는다고 기뻤을 텐데 금방 더러워져서 더 슬플 것 같아.'},\n", " {'role': 'speaker',\n", " 'text': '응, 나 진짜 새 신발 신고 기뻤었는데 이제는 신발 때문에 너무 슬퍼. 날씨 확인을 못한 내가 바보야.'},\n", " {'role': 'listener', 'text': '갑자기 내린 소나기였잖아. 예기치 못한 상황을 네 탓으로 돌리면서 슬퍼하지 마.'},\n", " {'role': 'speaker', 'text': '그렇지만 꼼꼼하지 못한 내 탓도 있는걸. 신발 얼마 신지도 못했는데 세척해야 돼.'},\n", " {'role': 'listener',\n", " 'text': '자기야, 너무 속상해하지 마. 새 신발을 신으면 신고식으로 한 번씩 밟아준다고 하잖아. 그런 일을 겪었다고 생각하자.'},\n", " {'role': 'speaker',\n", " 'text': '응, 근데 이번 일은 나 때문에 신발이 금방 더러워진 거라 속상해. 흙탕물을 피할 수도 있었는데 말이야.'},\n", " {'role': 'listener',\n", " 'text': '아무래도 이미 일어난 일에 아쉬운 점도 많겠지. 하지만 이미 벌어진 일에 계속 슬퍼하기보다는 문제를 해결하는 게 좋지 않을까? 신발을 세척하면 네 기분도 금방 나아질 거야.'},\n", " {'role': 'speaker', 'text': '응, 자기 말처럼 신발을 세척하면 기분이 나아질까?'},\n", " {'role': 'listener',\n", " 'text': '응, 신발 빨면 금방 얼룩이 지워질 거야. 그럼 원래대로 네 기분도 괜찮아지지 않을까? 신발도 세척하면서 기분도 전환하고 말이야.'},\n", " {'role': 'speaker', 'text': '자기 말 들으니까 그래야겠어. 내가 너무 감정에만 몰두해서 아무것도 안 했네.'},\n", " {'role': 'listener', 'text': '원래 가만히 있으면 감정이 더 몰아치잖아. 움직이면서 감정을 비워보자고.'},\n", " {'role': 'speaker', 'text': '응, 덕분에 이제 슬프지 않아. 조언해줘서 고마워!'}]}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data['train'][-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 81, "referenced_widgets": [ "58764caf824d4414b30bc8a6ee99a78c", "394d78a6f7a84851b465718bb6886a5f", "c961b04fd0e541bbac859d6658ab2efc", "19237562d4a54edc96902876c3c20a1c", "21413b06627a4f4aa7ba6455249d1d26", "d2c2cb6cd3664cbda3e7b97d8745a53f", "d674a2a412d344d3a540f26ffe80703a", "5ef069573fc64716896928f6716ef79d", "f58b23ff204341209d51dee828711afc", "8df2fbec9dea4814b38d78304560ac10", "9b42bd84796c4bb2afd5271477bbf1cf", "ebf2409c1903478387ae5ac96d58bf09", "c4fd78f0f4494be6a4f324e85c2f704d", "b8b88f6c1dfe4e659b16a8184ae2e1b2", "46ddcb9520e34a2d833ed6c53ed23f4f", "86ab49f67ba2477b863a864ece3e75ec", "c609aa7ed8ce4593a8c1434ee2b6c7ae", "95f97f1372384ebf843143ad8374a551", "17bb2e072a8248d1bc8a5e88590ce1cd", "82431339e5e94270989e72a654be6125", "55cdf404db7f4fef9f905c640498fad9", "05dcb62876fc4fcb81d0a1e47b8616d6" ] }, "id": "otjTV0-ztM_x", "outputId": "c543ffac-2d95-4518-c32c-fbcc59573e7c" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "58764caf824d4414b30bc8a6ee99a78c", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Map: 0%| | 0/3646 [00:00, ? examples/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ebf2409c1903478387ae5ac96d58bf09", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Map: 0%| | 0/3646 [00:00, ? examples/s]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# 텍스트로 변환\n", "data = data.map(\n", " lambda x: {\n", " 'text': \"\\n\".join([f\"{'여자' if line['role']=='speaker' else '남자'}: {line['text']}{EOT_TOKEN if line['role']!='speaker' else ''}\" for line in x['conversations']])\n", " }\n", ")\n", "\n", "# 학습 입력을 토크나이저로 변환\n", "# 텍스트 데이터를 모델이 이해할 수 있는 숫자 형태 즉, 토큰으로 변환한다는 뜻\n", "data = data.map(lambda samples: tokenizer(samples[\"text\"], truncation=True, max_length=2048), batched=True)" ] }, { "cell_type": "markdown", "metadata": { "id": "iWHtwqT7K4Mu" }, "source": [ "### LoRA 파라미터 항목\n", "\n", "- r=16 // LoRA rank (저차원 공간의 차원 수)\n", "- lora_alpha=32\t// scaling factor\n", "- target_modules // 어떤 모듈에 LoRA를 붙일지 지정 —> EEVE 계열 모델 구조에 특화\n", "- lora_dropout=0 // 드롭아웃 비활성화 —> 안정적 학습\n", "- bias=\"none\" // LoRA에서 bias 학습 안 함\n", "- use_rslora=False //Rank Stabilized LoRA 사용 안 함 (보통 False가 안정적)\n", "\n", "### 토큰 설정\n", "- 생성 결과 에서 발화자 구분이 필요할 때, 생성 멈춤 조건을 걸때, 생성 후 후처리 파싱할때 활용하기 위해 미리 확인차 설정\n", "- 각 항목에 대한 숫자는 해당 모델에 학습하며 이미 설정되어 있음\n", "\n", "### 학습 파라미터 결과\n", "- all params : 해당 모델의 전체 파라미터 수\n", "- trainable params : 이 중에서 LoRA로 학습 가능한 파라미터 수\n", "- trainable% : 전체 파라미터 중에서서 학습되는 비율" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "EXfC3BpLtN2f", "outputId": "f4267ffc-bc6d-4465-cbd8-8f0bf80c51a8" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "trainable params: 62914560 || all params: 5633347584 || trainable%: 1.1168236836422412\n" ] } ], "source": [ "# Gradient checkpointing 활성화 -> 메모리 최적화 기법\n", "model.gradient_checkpointing_enable()\n", "model = prepare_model_for_kbit_training(model)\n", "\n", "# 전체 파라미터 대비 LoRA로 학습되는 파라미터 비율 확인\n", "# 보통 수백억 파라미터 중 수십만 개만 학습(약 0.1%~0.3%)\n", "def print_trainable_parameters(model):\n", " \"\"\"\n", " Prints the number of trainable parameters in the model.\n", " \"\"\"\n", " trainable_params = 0\n", " all_param = 0\n", " for _, param in model.named_parameters():\n", " all_param += param.numel()\n", " if param.requires_grad:\n", " trainable_params += param.numel()\n", " print(\n", " f\"trainable params: {trainable_params} || all params: {all_param} || trainable%: {100 * trainable_params / all_param}\"\n", " )\n", "\n", "model.gradient_checkpointing_enable()\n", "# LoRA 설정\n", "config = LoraConfig(\n", " r=16,\n", " lora_alpha=32,\n", " target_modules = [\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\n", " \"gate_proj\", \"up_proj\", \"down_proj\",],\n", " lora_dropout=0,\n", " bias=\"none\",\n", " use_rslora = False,\n", ")\n", "\n", "# 원본 모델에 LoRA 어댑터 붙이기(trainable 파라미터만 추가)\n", "model = get_peft_model(model, config)\n", "print_trainable_parameters(model)\n", "\n", "#역할 토큰 넘버 저장\n", "tokenNum_ai = 33626 # \"남자\"\n", "tokenNum_human = 33269 # \"여자\"\n", "tokenNum_com = 714 # \":\"" ] }, { "cell_type": "markdown", "metadata": { "id": "1If0pHV6OPFO" }, "source": [ "##" ] }, { "cell_type": "markdown", "metadata": { "id": "1bp452wGYAhZ" }, "source": [ "## 학습 손실 계산을 재정의\n", "\n", "- '남자' 뒤에 나오는 부분만 학습하도록 손실을 마스킹하는 것\n", "- 즉, 모델은 '여자' 뒤의 내용은 예측하지 않도록 -100 마스크를 씌움" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "RY0ITNMitO_I" }, "outputs": [], "source": [ "class maskTrainer(Trainer):\n", " def __init__(self, *args, **kwargs):\n", " super().__init__(*args, **kwargs)\n", "\n", " def compute_loss(self, model, inputs, return_outputs=False):\n", " for x in range(len(inputs['labels'])):\n", " # print(tokenizer.decode(inputs['labels'][x]))\n", "\n", " maskindex1 = (inputs['labels'][x]==tokenNum_human).nonzero()[:, 0].cpu()\n", " temp = 0\n", " for i, index in enumerate(maskindex1):\n", " if (inputs['labels'][x][index+1] != tokenNum_com):\n", " maskindex1 = np.delete(maskindex1, i-temp)\n", " temp += 1\n", "\n", " maskindex2 = (inputs['labels'][x]==tokenNum_ai).nonzero()[:, 0].cpu()\n", " temp = 0\n", " for i, index in enumerate(maskindex2):\n", " if (inputs['labels'][x][index+1] != tokenNum_com):\n", " maskindex2 = np.delete(maskindex2, i-temp)\n", " temp += 1\n", "\n", " for i in range(len(maskindex1)):\n", " ai_index = -1\n", " for num in maskindex2:\n", " if (maskindex1[i] < num):\n", " ai_index = num\n", " break\n", " if (ai_index == -1):\n", " inputs['labels'][x][maskindex1[i]+2:] = -100\n", " else:\n", " inputs['labels'][x][maskindex1[i]+2:ai_index+2] = -100\n", " # print(inputs['labels'][x])\n", "\n", " outputs = model(**inputs)\n", " loss = outputs['loss']\n", " return (loss,outputs) if return_outputs else loss\n", "\n", "# tokenizer.pad_token = tokenizer.eos_token" ] }, { "cell_type": "markdown", "metadata": { "id": "svg6ImYiZE0V" }, "source": [ "# 모델 학습 및 파라미터 설정" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 553 }, "id": "iBWy6eGztQL-", "outputId": "d12504b6-3cf2-4dda-ba52-06c08cfaac09" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "No label_names provided for model class `PeftModel`. Since `PeftModel` hides base models input arguments, if label_names is not given, label_names can't be set automatically within `Trainer`. Note that empty label_names list will be used instead.\n" ] }, { "data": { "text/html": [ "\n", "
| Step | \n", "Training Loss | \n", "
|---|---|
| 500 | \n", "2.231800 | \n", "
| 1000 | \n", "2.214900 | \n", "
| 1500 | \n", "2.218900 | \n", "
| 2000 | \n", "2.181500 | \n", "
| 2500 | \n", "2.195300 | \n", "
| 3000 | \n", "2.144400 | \n", "
| 3500 | \n", "2.145200 | \n", "
| 4000 | \n", "1.834900 | \n", "
| 4500 | \n", "1.688400 | \n", "
| 5000 | \n", "1.673200 | \n", "
| 5500 | \n", "1.657700 | \n", "
| 6000 | \n", "1.630900 | \n", "
| 6500 | \n", "1.614700 | \n", "
| 7000 | \n", "1.612100 | \n", "
"
],
"text/plain": [
"