{ "cells": [ { "cell_type": "markdown", "id": "3f46e383", "metadata": {}, "source": [ "## Hugging Face\n", "\n", "Hugging Face is an online model repository that you can access at https://huggingfact.co\n", "\n", "On the Hugging Face site you will find more than 2 million models that users have contributed. These models are all free to download and use.\n", "\n", "Given the huge number of models on the site, finding an appropriate model can be a challenge. To make it easier to find what you are looking for, the Hugging Face site offers a number of filtering tools.\n", "\n", "To access the models, click the models button that appears at the top of the landing page.\n", "\n", "To limit your search for models designed for a particular application, go to the Tasks area on the left hand side of the models page and click the button for the task you need to perform. There are many tasks available, so you should click the +42 button under Tasks to see an expanded view of available tasks." ] }, { "cell_type": "markdown", "id": "c04c55ce", "metadata": {}, "source": [ "### Package prerequisites\n", "\n", "To run the examples below, evaluate this first cell to install some packages you will need. One of these packages is the Hugging Face Transformers library, which you will need to run models that use transformers." ] }, { "cell_type": "code", "execution_count": 41, "id": "c77a6b75", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: transformers in /home/joe/work/torchenv/lib/python3.12/site-packages (4.57.0)\n", "Requirement already satisfied: datasets in /home/joe/work/torchenv/lib/python3.12/site-packages (4.2.0)\n", "Requirement already satisfied: sacremoses in /home/joe/work/torchenv/lib/python3.12/site-packages (0.1.1)\n", "Requirement already satisfied: filelock in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (3.13.1)\n", "Requirement already satisfied: huggingface-hub<1.0,>=0.34.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (0.35.3)\n", "Requirement already satisfied: numpy>=1.17 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (1.26.4)\n", "Requirement already satisfied: packaging>=20.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (25.0)\n", "Requirement already satisfied: pyyaml>=5.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (6.0.2)\n", "Requirement already satisfied: regex!=2019.12.17 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (2025.9.1)\n", "Requirement already satisfied: requests in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (2.32.5)\n", "Requirement already satisfied: tokenizers<=0.23.0,>=0.22.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (0.22.1)\n", "Requirement already satisfied: safetensors>=0.4.3 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (0.6.2)\n", "Requirement already satisfied: tqdm>=4.27 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers) (4.67.1)\n", "Requirement already satisfied: pyarrow>=21.0.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from datasets) (21.0.0)\n", "Requirement already satisfied: dill<0.4.1,>=0.3.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from datasets) (0.4.0)\n", "Requirement already satisfied: pandas in /home/joe/work/torchenv/lib/python3.12/site-packages (from datasets) (2.3.2)\n", "Requirement already satisfied: httpx<1.0.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from datasets) (0.28.1)\n", "Requirement already satisfied: xxhash in /home/joe/work/torchenv/lib/python3.12/site-packages (from datasets) (3.6.0)\n", "Requirement already satisfied: multiprocess<0.70.17 in /home/joe/work/torchenv/lib/python3.12/site-packages (from datasets) (0.70.16)\n", "Requirement already satisfied: fsspec<=2025.9.0,>=2023.1.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (2024.6.1)\n", "Requirement already satisfied: click in /home/joe/work/torchenv/lib/python3.12/site-packages (from sacremoses) (8.3.0)\n", "Requirement already satisfied: joblib in /home/joe/work/torchenv/lib/python3.12/site-packages (from sacremoses) (1.5.2)\n", "Requirement already satisfied: torch>=2.2 in /home/joe/work/torchenv/lib/python3.12/site-packages (from transformers[torch]) (2.8.0+cu129)\n", "Collecting accelerate>=0.26.0 (from transformers[torch])\n", " Downloading accelerate-1.11.0-py3-none-any.whl.metadata (19 kB)\n", "Requirement already satisfied: psutil in /home/joe/work/torchenv/lib/python3.12/site-packages (from accelerate>=0.26.0->transformers[torch]) (7.0.0)\n", "Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (3.13.0)\n", "Requirement already satisfied: anyio in /home/joe/work/torchenv/lib/python3.12/site-packages (from httpx<1.0.0->datasets) (4.10.0)\n", "Requirement already satisfied: certifi in /home/joe/work/torchenv/lib/python3.12/site-packages (from httpx<1.0.0->datasets) (2025.8.3)\n", "Requirement already satisfied: httpcore==1.* in /home/joe/work/torchenv/lib/python3.12/site-packages (from httpx<1.0.0->datasets) (1.0.9)\n", "Requirement already satisfied: idna in /home/joe/work/torchenv/lib/python3.12/site-packages (from httpx<1.0.0->datasets) (3.10)\n", "Requirement already satisfied: h11>=0.16 in /home/joe/work/torchenv/lib/python3.12/site-packages (from httpcore==1.*->httpx<1.0.0->datasets) (0.16.0)\n", "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/joe/work/torchenv/lib/python3.12/site-packages (from huggingface-hub<1.0,>=0.34.0->transformers) (4.15.0)\n", "Requirement already satisfied: hf-xet<2.0.0,>=1.1.3 in /home/joe/work/torchenv/lib/python3.12/site-packages (from huggingface-hub<1.0,>=0.34.0->transformers) (1.1.10)\n", "Requirement already satisfied: charset_normalizer<4,>=2 in /home/joe/work/torchenv/lib/python3.12/site-packages (from requests->transformers) (3.4.3)\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from requests->transformers) (2.5.0)\n", "Requirement already satisfied: setuptools in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (80.9.0)\n", "Requirement already satisfied: sympy>=1.13.3 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (1.13.3)\n", "Requirement already satisfied: networkx in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (3.3)\n", "Requirement already satisfied: jinja2 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (3.1.6)\n", "Requirement already satisfied: nvidia-cuda-nvrtc-cu12==12.9.86 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.9.86)\n", "Requirement already satisfied: nvidia-cuda-runtime-cu12==12.9.79 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.9.79)\n", "Requirement already satisfied: nvidia-cuda-cupti-cu12==12.9.79 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.9.79)\n", "Requirement already satisfied: nvidia-cudnn-cu12==9.10.2.21 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (9.10.2.21)\n", "Requirement already satisfied: nvidia-cublas-cu12==12.9.1.4 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.9.1.4)\n", "Requirement already satisfied: nvidia-cufft-cu12==11.4.1.4 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (11.4.1.4)\n", "Requirement already satisfied: nvidia-curand-cu12==10.3.10.19 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (10.3.10.19)\n", "Requirement already satisfied: nvidia-cusolver-cu12==11.7.5.82 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (11.7.5.82)\n", "Requirement already satisfied: nvidia-cusparse-cu12==12.5.10.65 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.5.10.65)\n", "Requirement already satisfied: nvidia-cusparselt-cu12==0.7.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (0.7.1)\n", "Requirement already satisfied: nvidia-nccl-cu12==2.27.3 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (2.27.3)\n", "Requirement already satisfied: nvidia-nvtx-cu12==12.9.79 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.9.79)\n", "Requirement already satisfied: nvidia-nvjitlink-cu12==12.9.86 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (12.9.86)\n", "Requirement already satisfied: nvidia-cufile-cu12==1.14.1.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (1.14.1.1)\n", "Requirement already satisfied: triton==3.4.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from torch>=2.2->transformers[torch]) (3.4.0)\n", "Requirement already satisfied: python-dateutil>=2.8.2 in /home/joe/work/torchenv/lib/python3.12/site-packages (from pandas->datasets) (2.9.0.post0)\n", "Requirement already satisfied: pytz>=2020.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from pandas->datasets) (2025.2)\n", "Requirement already satisfied: tzdata>=2022.7 in /home/joe/work/torchenv/lib/python3.12/site-packages (from pandas->datasets) (2025.2)\n", "Requirement already satisfied: aiohappyeyeballs>=2.5.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (2.6.1)\n", "Requirement already satisfied: aiosignal>=1.4.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (1.4.0)\n", "Requirement already satisfied: attrs>=17.3.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (25.3.0)\n", "Requirement already satisfied: frozenlist>=1.1.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (1.8.0)\n", "Requirement already satisfied: multidict<7.0,>=4.5 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (6.7.0)\n", "Requirement already satisfied: propcache>=0.2.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (0.4.1)\n", "Requirement already satisfied: yarl<2.0,>=1.17.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.9.0,>=2023.1.0->datasets) (1.22.0)\n", "Requirement already satisfied: six>=1.5 in /home/joe/work/torchenv/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas->datasets) (1.17.0)\n", "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from sympy>=1.13.3->torch>=2.2->transformers[torch]) (1.3.0)\n", "Requirement already satisfied: sniffio>=1.1 in /home/joe/work/torchenv/lib/python3.12/site-packages (from anyio->httpx<1.0.0->datasets) (1.3.1)\n", "Requirement already satisfied: MarkupSafe>=2.0 in /home/joe/work/torchenv/lib/python3.12/site-packages (from jinja2->torch>=2.2->transformers[torch]) (3.0.2)\n", "Downloading accelerate-1.11.0-py3-none-any.whl (375 kB)\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m375.8/375.8 kB\u001b[0m \u001b[31m8.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m:00:01\u001b[0m\n", "\u001b[?25hInstalling collected packages: accelerate\n", "Successfully installed accelerate-1.11.0\n" ] } ], "source": [ "!pip install transformers datasets sacremoses transformers[torch]" ] }, { "cell_type": "markdown", "id": "3e8205c7", "metadata": {}, "source": [ "### Some Examples\n", "\n", "The examples below are adapted from the book Hugging Face in Action by Wei-Meng Lee." ] }, { "cell_type": "markdown", "id": "8cc99209", "metadata": {}, "source": [ "### Datasets\n", "\n", "Hugging Face is also a repository for datasets. The datasets package from Hugging Face makes it easy to download and use datasets from Hugging Face.\n", "\n", "In much the same way that you can browse models on the Hugging Face site you can also browse datasets. To go to the datasets page, simply click the Datasets button at the top of the page. You can filter datasets by applications in much the same way that you can filter models." ] }, { "cell_type": "markdown", "id": "3e9baaa6", "metadata": {}, "source": [ "### Example Dataset\n", "\n", "For my first example I am going to set up a model to do text classification. To provide some data for us to use with the model I found a useful example dataset, the Yelp polarity dataset. This dataset contains a large number of reviews downloaded from Yelp. Each review is labeled as either a negative review or a positive review." ] }, { "cell_type": "code", "execution_count": 1, "id": "09a1b5c8", "metadata": {}, "outputs": [], "source": [ "from datasets import load_dataset\n", "\n", "ds = load_dataset(\"yelp_polarity\")" ] }, { "cell_type": "markdown", "id": "a74033d1", "metadata": {}, "source": [ "Looking at some examples can show us how the items in the dataset are structured." ] }, { "cell_type": "code", "execution_count": 2, "id": "cd5650eb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'text': [\"4 Words....DOUBLE DOUBLE ANIMAL STYLE.....!! \\\\n\\\\n It is just the most DELISH Burger Goodness You Will Ever Put In Your Mouth!! You Should Get The Fries Animal Style Too...BUTTT...Plan To Share With Your Fave Friend....B/C Otherwise You Will Be Too Stuffed To Finish Them!! \\\\n\\\\nI Love The Tropicana Location For 2 Reasons....The First Being The Staff Is Totally Fun and Helpful....and The Second and Deciding Vote Is B/c The Staff Is TOTALLY SMOKING HOT!! :-) Why Lie? It's Yelp??!! All In and Out Have Great Customer Service....But Not All Have A SMOKING HOT STAFF......\\\\n\\\\nSo Really, If I Can Stuff My Face With DELISH BURGER GOODNESS (Across The Parking Lot In Front Of The Retail Store) and STARE At Hot Boys.....Why Would I Go Anywhere Else??!!\",\n", " \"We love the Vig. Been their many times. We ordered take out this evening. Pad Thai. My friend was enjoying his meal and bit into a piece of wire that was in his pad Thai. Luckily he didn't cut or slice his mouth or swallow it but it was shocking this was in his food. I was not happy. Never had that happen before.\",\n", " 'The BurGR is a beautifully set out restaurant and full of lots of sharp-looking waitstaff, and despite a lengthy line for group-dining, as a single I was able to sit right down at the bar. I ordered one of the special burger offereings, the uber cheeseburger medium well. I think of burger-medium well as \\\\\"\"no pink in the middle,\\\\\"\" or passably the tiniest bit of pink in the middle as ground beef should be cooked much more thoroughly than, say, a beef steak. Many restaurants will not even have a medium-rare burger as an option owing to the chance of food poisoning from undercooked hamburgers. When the burger arrived 25 minutes later, it looked gorgeous on its puffy roll, with the cheese nicely melted and the beef sporting a glazed, glistening look. But the first bite into the burger crushed my enthusiasm. If the burger was 1/2 inch thick, then the middle 1/4 inch all the way through the burger was pink. 2 days later I am comfortable stating that the burger did not make me sick, but for a guy\\'s whose reputation is built on quality control, how he let this burger come out of his kitchen so underdone is a mystery. I\\'ll be curious to see what other reports come out of this restaurant.',\n", " 'I ordered my usually \\\\\"\"white peach by starbuzz\\\\\"\" I waited for about 15-20 mins and received my hookah to only be let down.\\\\n\\\\nThey use instant lights :( not only does that later the flavor but it also makes the hookah have a chemical taste \\\\n\\\\nI\\'ll never purchase a hookah from there again !',\n", " \"I've been coming here for the past few years and it's still one of my favorites.\\\\n\\\\nHikari is one of the best AYCE places in Las Vegas for sushi. While the actual list of items on their AYCE may not initially seem like a lot, I dare you to work your way down the list. Unlike many other sushi bars that offer AYCE deals, Hikari has both Uni and Oysters on it's AYCE list. Also, sashimi is offered as part of the AYCE which is almost NEVER available.\\\\n\\\\nMy best suggestion is to sit at the sushi bar as the service is quicker and you can get to know the staff. They'll try to help guide you along if you're not an experienced sushi eater. Just ask! :)\",\n", " \"Unfortunately my rancor at this visit prevents me from trying to put any humor into this review. In short, my $2.75 ceviche tostada was overwhelmingly saturated with limes and ridiculously soggy. When asked about their best soup, I was told to get their Caldo De Rez, which was a $7 admittedly large bowl filled cabbage, carrots, and literally 4 pieces of tough, thumbnail sized beef. I tried to give the evil eye to the server as I left but he couldn't summon the courage and kept staring at his popcorn machine turned into chip dispenser. Look me in the eye when you lie to me, damn you. Ugh. Hatred. Fury, rage.\",\n", " \"I had higher hopes for this place, the chicken wasn't well seasoned there was no kick to it. Corn bread was too sweet, the only thing I did enjoy from this joint was the rice with gravy. Overrated! I give it a 2.5.\",\n", " 'The free Chips and salsa were the best part of our meal. Ordered the tortilla soup and Pollo fundido and everything came out room temperature. Twice our server asked is if we would like more chips and salsa, twice we said YES and we never did get them. And dont sit on the patio, you will have to fight of the flies.',\n", " 'Lunch on the way to the airport. An excellent way to end our inaugural Vegas trip.\\\\n\\\\nEverything was what I read about and expected. The dingy, sketchy, vacant strip mall. The low key restaurant facade and interior. The extensive menu and wine list. And then there was the food. I have been eating Thai food for years, with lots of authentic, top notch Thai restaurants in my neighborhood. Lotus blew them away.\\\\n\\\\nThe tod mun plar (deep fried fish cake) was cooked perfectly and was a great way to start our meal. I then had the kang renu nakorn with chicken, which is a red curry but without coconut milk and lots of vegetables. Spicy and tons of flavor, I think the best part was how it completely cured my hangover. My husband had the drunken noodles with soft shell crab, which was a phenomenal dish. \\\\n\\\\nI liked that this place was mostly locals; while were there it was mostly hospital and office workers on their lunch break.\\\\n\\\\nThe lunch buffet looked excellent and is probably worth trying as well.\\\\n\\\\nI am glad we were able to get here and I hope we return one day.',\n", " \"First off the food was ok. Just ok. One of our diners had the ribeye Oscar style and it was so tough he didn't even finish half of it. What a waste. Looked dry from where I sat. Hubby had Etouffee and he liked it but had better elsewhere. We all had Caesar salads, very tasty and the only dressing not made in-house. I had the Shrimp Brochette Appetizer with a salad for dinner, the shrimp with bacon could have cooked a little longer so all meats could cook through. Had a stomach problem later that evening. Bread Pudding, good, Beinget too doughy and overly powdered with sugar. Nothing spicy, though I thought the Etouffee would be.\\\\n\\\\nService, well we had a reservation and the hostess wanted to seat us at the first table as you walked in to the main dining room when most all tables at that time were empty. We asked for another table and she really didn't want to move us any further than the table next to it because as she said, later reservations were planned for those tables. Why in the world would you seat people at the first table everyone has to walk by when there were available tables the same size further in? Our waiter and his assistant were good! \\\\n\\\\nFriends have been here and loved it. Not sure if there's been a change somewhere down the line. We probably won't be back.\"],\n", " 'label': [1, 0, 0, 0, 1, 0, 0, 0, 1, 0]}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "examples = ds['test'].shuffle()[:10]\n", "examples" ] }, { "cell_type": "markdown", "id": "d654b06b", "metadata": {}, "source": [ "The structure here is a little bit unusual. What we have here is a dictionary with two keys: label and text. The value for text is a list of review strings, and the value for label is a list of negative/positive values.\n", "\n", "In preparation for our model, let's isolate the text from these example reviews. Since the model we will work with below has a maximum token limit of 512 tokens, we will also need to truncate any reviews that have too many words in them." ] }, { "cell_type": "code", "execution_count": 3, "id": "679aeeb5", "metadata": {}, "outputs": [], "source": [ "texts = list(map(lambda str: str if len(str) < 500 else str[:500],examples['text']))" ] }, { "cell_type": "markdown", "id": "9e6b915a", "metadata": {}, "source": [ "Next, we bring in a model that can do text classification. To load and set up a model we use the pipeline() constructor from the Hugging Face Transformers library.\n", "\n", "When setting up a pipeline we have to specify the task we want the pipeline to perform along with the name of the model." ] }, { "cell_type": "code", "execution_count": 4, "id": "1bddf6fd", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Device set to use cuda:0\n" ] } ], "source": [ "from transformers import pipeline\n", "\n", "pipe = pipeline(\"text-classification\", model=\"distilbert/distilbert-base-uncased-finetuned-sst-2-english\")" ] }, { "cell_type": "markdown", "id": "08cf5f46", "metadata": {}, "source": [ "Note that the pipeline automatically gets deployed to the GPU on our machine.\n", "\n", "To use the pipeline, we simply pass it a set of inputs." ] }, { "cell_type": "code", "execution_count": 5, "id": "4fe4e88e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'label': 'POSITIVE', 'score': 0.7864517569541931},\n", " {'label': 'NEGATIVE', 'score': 0.8345455527305603},\n", " {'label': 'POSITIVE', 'score': 0.9953063130378723},\n", " {'label': 'NEGATIVE', 'score': 0.9882545471191406},\n", " {'label': 'NEGATIVE', 'score': 0.8934980034828186},\n", " {'label': 'NEGATIVE', 'score': 0.9995410442352295},\n", " {'label': 'NEGATIVE', 'score': 0.9960170388221741},\n", " {'label': 'POSITIVE', 'score': 0.8711990118026733},\n", " {'label': 'POSITIVE', 'score': 0.9945301413536072},\n", " {'label': 'NEGATIVE', 'score': 0.9970707893371582}]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pipe(texts)" ] }, { "cell_type": "markdown", "id": "898394c0", "metadata": {}, "source": [ "By default, the classifier we have chosen has two categories: positive and negative.\n", "\n", "We can compare these results with the original labels for these examples." ] }, { "cell_type": "code", "execution_count": 6, "id": "85b90922", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 0, 0, 0, 1, 0, 0, 0, 1, 0]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "examples['label']" ] }, { "cell_type": "markdown", "id": "f0140025", "metadata": {}, "source": [ "The alignment here is not the greatest. Later on in this notebook we will produce a model that can do better on this dataset." ] }, { "cell_type": "markdown", "id": "edddca96", "metadata": {}, "source": [ "To use a pipeline you will need to specify the task for the pipeline. If you don't know what options are available for the task parameter, you can pass an incorrect value for the task. This will trigger an exception, and you can print the exception to see a message listing the valid values for the task parameter." ] }, { "cell_type": "code", "execution_count": 5, "id": "c97d869a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"Unknown task dummy, available tasks are ['audio-classification', 'automatic-speech-recognition', 'depth-estimation', 'document-question-answering', 'feature-extraction', 'fill-mask', 'image-classification', 'image-feature-extraction', 'image-segmentation', 'image-text-to-text', 'image-to-image', 'image-to-text', 'keypoint-matching', 'mask-generation', 'ner', 'object-detection', 'question-answering', 'sentiment-analysis', 'summarization', 'table-question-answering', 'text-classification', 'text-generation', 'text-to-audio', 'text-to-speech', 'text2text-generation', 'token-classification', 'translation', 'video-classification', 'visual-question-answering', 'vqa', 'zero-shot-audio-classification', 'zero-shot-classification', 'zero-shot-image-classification', 'zero-shot-object-detection', 'translation_XX_to_YY']\"\n" ] } ], "source": [ "from transformers import pipeline\n", "try:\n", " dummy_pipeline = pipeline(task=\"dummy\")\n", "except Exception as e:\n", " print(e)" ] }, { "cell_type": "markdown", "id": "727e1f6c", "metadata": {}, "source": [ "## Fine Tuning a Model\n", "\n", "The classifier we used for our pipeline performs resonably well right out of the box on the Yelp dataset. Nonetheless, it will occasionally misfire. The reason for this is that the classifier is a very generic classifier. To make it more focussed for the specific task of evaluating reviews we can start with a base model and fine tune it using examples from our dataset.\n", "\n", "The next few cells demonstrate how to do this." ] }, { "cell_type": "code", "execution_count": 11, "id": "f5ccafde", "metadata": {}, "outputs": [], "source": [ "from transformers import AutoTokenizer\n", "\n", "model_checkpoint = \"distilbert-base-uncased\"\n", "tokenizer = AutoTokenizer.from_pretrained(model_checkpoint) \n", "\n", "def tokenize_function(examples): \n", " return tokenizer(examples[\"text\"],\n", " padding = \"max_length\",\n", " truncation = True,\n", " max_length = 512)\n", "\n", "tokenized_datasets = ds.map( \n", " tokenize_function,\n", " batched=True)" ] }, { "cell_type": "markdown", "id": "99ee7e01", "metadata": {}, "source": [ "In preparation for training we will convert all of the text in our trainging and test datasets into tokens. To do this we will use a tokenizer that is designed to work with the base model we will be fine tuning below.\n", "\n", "As our base model we will be using the Distilbert model, which is a condensed version of the popular BERT model." ] }, { "cell_type": "code", "execution_count": 12, "id": "c2592d99", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight', 'pre_classifier.bias', 'pre_classifier.weight']\n", "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n" ] }, { "data": { "text/plain": [ "DistilBertForSequenceClassification(\n", " (distilbert): DistilBertModel(\n", " (embeddings): Embeddings(\n", " (word_embeddings): Embedding(30522, 768, padding_idx=0)\n", " (position_embeddings): Embedding(512, 768)\n", " (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n", " (dropout): Dropout(p=0.1, inplace=False)\n", " )\n", " (transformer): Transformer(\n", " (layer): ModuleList(\n", " (0-5): 6 x TransformerBlock(\n", " (attention): DistilBertSdpaAttention(\n", " (dropout): Dropout(p=0.1, inplace=False)\n", " (q_lin): Linear(in_features=768, out_features=768, bias=True)\n", " (k_lin): Linear(in_features=768, out_features=768, bias=True)\n", " (v_lin): Linear(in_features=768, out_features=768, bias=True)\n", " (out_lin): Linear(in_features=768, out_features=768, bias=True)\n", " )\n", " (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n", " (ffn): FFN(\n", " (dropout): Dropout(p=0.1, inplace=False)\n", " (lin1): Linear(in_features=768, out_features=3072, bias=True)\n", " (lin2): Linear(in_features=3072, out_features=768, bias=True)\n", " (activation): GELUActivation()\n", " )\n", " (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n", " )\n", " )\n", " )\n", " )\n", " (pre_classifier): Linear(in_features=768, out_features=768, bias=True)\n", " (classifier): Linear(in_features=768, out_features=2, bias=True)\n", " (dropout): Dropout(p=0.2, inplace=False)\n", ")" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from transformers import AutoModelForSequenceClassification\n", "import torch\n", "\n", "model = AutoModelForSequenceClassification.from_pretrained( \n", " model_checkpoint, num_labels = 2)\n", "\n", "device = torch.device(\n", " \"cuda\" if torch.cuda.is_available() else \"cpu\")\n", "\n", "model.to(device)" ] }, { "cell_type": "markdown", "id": "00e6fc3c", "metadata": {}, "source": [ "The code in the next cell will run 3 epochs of training to fine tune our base model.\n", "\n", "Since our dataset has over half a million entries, it will take a while to run 3 epochs of training. On a reasonably powerful GPU this next step will take over three hours." ] }, { "cell_type": "code", "execution_count": 13, "id": "49640dbd", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " \n", " [105000/105000 3:23:30, Epoch 3/3]\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
EpochTraining LossValidation Loss
10.0894000.096168
20.1461000.100594
30.0325000.117540

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "TrainOutput(global_step=105000, training_loss=0.07284961530546924, metrics={'train_runtime': 12210.3422, 'train_samples_per_second': 137.588, 'train_steps_per_second': 8.599, 'total_flos': 2.2254522974208e+17, 'train_loss': 0.07284961530546924, 'epoch': 3.0})" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from transformers import Trainer, TrainingArguments\n", "\n", "training_args = TrainingArguments( \n", " output_dir = \"./results\", \n", " eval_strategy = \"epoch\", \n", " save_strategy = \"epoch\", \n", " learning_rate = 2e-5, \n", " per_device_train_batch_size = 16, \n", " per_device_eval_batch_size = 16, \n", " num_train_epochs = 3, \n", " weight_decay = 0.01, \n", " logging_dir = \"./logs\", \n", " logging_steps = 10, \n", " save_steps = 500, \n", " load_best_model_at_end = True, \n", ")\n", "\n", "trainer = Trainer( \n", " model = model,\n", " args = training_args,\n", " train_dataset = tokenized_datasets[\"train\"],\n", " eval_dataset = tokenized_datasets[\"test\"],\n", ")\n", "\n", "trainer.train()" ] }, { "cell_type": "markdown", "id": "d32bfcce", "metadata": {}, "source": [ "Once the training is complete we will save our tokenizer and our fine tuned model." ] }, { "cell_type": "code", "execution_count": 14, "id": "61a0024a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('./results/final_tokenizer/tokenizer_config.json',\n", " './results/final_tokenizer/special_tokens_map.json',\n", " './results/final_tokenizer/vocab.txt',\n", " './results/final_tokenizer/added_tokens.json',\n", " './results/final_tokenizer/tokenizer.json')" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.save_pretrained(\"./results/final_model\") \n", "tokenizer.save_pretrained(\"./results/final_tokenizer\") " ] }, { "cell_type": "markdown", "id": "2ac1bb07", "metadata": {}, "source": [ "The next cell demonstrates how to run an example sentence through the model. For the example here I will pick on of the test examples that the first model failed on earlier in this notebook." ] }, { "cell_type": "code", "execution_count": 15, "id": "c5418718", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Sentiment: Negative (Confidence: 0.86)\n" ] } ], "source": [ "from transformers import AutoTokenizer, AutoModelForSequenceClassification\n", "import torch\n", "\n", "new_model = AutoModelForSequenceClassification.from_pretrained(\"./results/final_model\")\n", "new_tokenizer = AutoTokenizer.from_pretrained(\"./results/final_tokenizer\")\n", "\n", "new_model.to(device)\n", "\n", "sentence = texts[2]\n", "\n", "inputs = new_tokenizer(sentence, \n", " return_tensors = \"pt\",\n", " padding = True,\n", " truncation = True,\n", " max_length = 512)\n", "\n", "inputs = {key: value.to(device) for key, value in inputs.items()} \n", "\n", "new_model.eval() \n", "\n", "with torch.no_grad():\n", " outputs = new_model(**inputs) \n", "logits = outputs.logits \n", "probabilities = torch.nn.functional.softmax(logits, dim=-1) \n", "predicted_class = torch.argmax(probabilities, dim=-1).item() \n", "\n", "if predicted_class == 1: \n", " print(f\"Sentiment: Positive (Confidence: {probabilities[0][1].item():.2f})\")\n", "else:\n", " print(f\"Sentiment: Negative (Confidence: {probabilities[0][0].item():.2f})\")" ] }, { "cell_type": "markdown", "id": "2e318831", "metadata": {}, "source": [ "More information on fine-tuning is available at\n", "\n", "https://huggingface.co/docs/transformers/en/training" ] }, { "cell_type": "markdown", "id": "c88e60f6", "metadata": {}, "source": [ "### Another application\n", "\n", "To demonstrate that Hugging Face NLP models can be used for a wide range of applications, our next example will involve a translation task.\n", "\n", "Specifically, we will set up and use a model that can translate English text to German." ] }, { "cell_type": "markdown", "id": "7e5b819e", "metadata": {}, "source": [ "Since this is a more advanced task, we will not use the simplest approach, which is to use a pipeline.\n", "\n", "The next simplest alternative is to use a separate tokenizer and a generation model." ] }, { "cell_type": "code", "execution_count": 16, "id": "0049fa7c", "metadata": {}, "outputs": [], "source": [ "from transformers import FSMTForConditionalGeneration, FSMTTokenizer\n", "\n", "model_name = \"facebook/wmt19-en-de\"\n", "tokenizer = FSMTTokenizer.from_pretrained(model_name)\n", "model = FSMTForConditionalGeneration.from_pretrained(model_name)\n", "\n", "def translate(inputs):\n", " tokens = tokenizer.encode(inputs, return_tensors=\"pt\") \n", " outputs = model.generate(tokens)\n", " translation = tokenizer.decode(outputs[0], skip_special_tokens=True)\n", " return translation" ] }, { "cell_type": "markdown", "id": "030e4cce", "metadata": {}, "source": [ "As an example, we will translate one of the Yelp reviews from above into German." ] }, { "cell_type": "code", "execution_count": 25, "id": "60765b94", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\"I've been coming here for the past few years and it's still one of my favorites.\\\\n\\\\nHikari is one of the best AYCE places in Las Vegas for sushi. While the actual list of items on their AYCE may not initially seem like a lot, I dare you to work your way down the list. Unlike many other sushi bars that offer AYCE deals, Hikari has both Uni and Oysters on it's AYCE list. Also, sashimi is offered as part of the AYCE which is almost NEVER available.\\\\n\\\\nMy best suggestion is to sit at the sushi ba\"" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "texts[4]" ] }, { "cell_type": "code", "execution_count": 26, "id": "715c84de", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Ich komme seit ein paar Jahren hierher und es ist immer noch einer meiner Favoriten.\\\\ n\\\\ nHikari ist einer der besten AYCE-Orte in Las Vegas für Sushi-Angebote. Auch wenn die aktuelle Liste der AYCE-Angebote auf den man sich auf den ersten Blick vielleicht nicht besonders gut finden mag, aber ich traue, aber ich mir, aber ich mir schon, aber ich mir schon, dass man sich doch einen Weg nach unten nach unten nach unten zu arbeiten. Im Gegensatz zu. Im Gegensatz zu vielen. Im Gegensatz zu vielen anderen Sushi-Bars, die Liste, in Hikari habe ich traue ich mir, in dieser Liste, in dieser Liste, die ich mir, in dieser Liste zu. Im Hikari habe ich mir schon an. Im AYAYCE-Bars habe ich mich doch nicht so weit nach unten zu. Im Gegensatz zu. Im Hikari habe ich mich hier habe'" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "translate(texts[4])" ] }, { "cell_type": "markdown", "id": "12d5e361", "metadata": {}, "source": [ "### Learn More\n", "\n", "More information about the Hugging Face Transformers library is available at\n", "\n", "https://huggingface.co/docs/transformers/index" ] } ], "metadata": { "kernelspec": { "display_name": "torchenv (3.12.3)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }