Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"Resumen de textos","local":"resumen-de-textos","sections":[{"title":"Preparación de un corpus multilingüe","local":"preparacion-de-un-corpus-multilingue","sections":[],"depth":2},{"title":"Modelos para resumen de textos","local":"modelos-para-resumen-de-textos","sections":[],"depth":2},{"title":"Preprocesamiento de los datos","local":"preprocesamiento-de-los-datos","sections":[],"depth":2},{"title":"Métricas para resumen de textos","local":"metricas-para-resumen-de-textos","sections":[{"title":"Crear una línea base sólida","local":"crear-una-linea-base-solida","sections":[],"depth":3}],"depth":2},{"title":"Ajuste fino de mT5 con la API Trainer","local":"ajuste-fino-de-mt5-con-la-api-trainer","sections":[],"depth":2},{"title":"Ajuste fino de mT5 con Keras","local":"ajuste-fino-de-mt5-con-keras","sections":[],"depth":2},{"title":"Ajuste fino de mT5 con 🤗 Accelerate","local":"ajuste-fino-de-mt5-con-accelerate","sections":[{"title":"Preparando todo para el entrenamiento","local":"preparando-todo-para-el-entrenamiento","sections":[],"depth":3},{"title":"Bucle de entrenamiento","local":"bucle-de-entrenamiento","sections":[],"depth":3}],"depth":2},{"title":"Uso de tu modelo ajustado","local":"uso-de-tu-modelo-ajustado","sections":[],"depth":2}],"depth":1}"/> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/entry/start.DV9gcfqJ.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/DfLptDcl.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/BA_dZbsI.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/entry/app.C68Ze5cV.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/C0jRxzmK.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/DvbUaM1Q.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/BtJu3x8T.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/DsnmJJEf.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/nodes/0.BzDzkAzS.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/C3nIf8Go.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/nodes/44.gi8AAMiw.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/DX9wbpOW.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/b7zOzquf.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/r2R_RyXK.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/C-UOVayx.js" rel="modulepreload"> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/chunks/Khighb8g.js" rel="modulepreload"> | |
| <!--m7mm2j--><meta name="hf:doc:metadata" content="{"title":"Resumen de textos","local":"resumen-de-textos","sections":[{"title":"Preparación de un corpus multilingüe","local":"preparacion-de-un-corpus-multilingue","sections":[],"depth":2},{"title":"Modelos para resumen de textos","local":"modelos-para-resumen-de-textos","sections":[],"depth":2},{"title":"Preprocesamiento de los datos","local":"preprocesamiento-de-los-datos","sections":[],"depth":2},{"title":"Métricas para resumen de textos","local":"metricas-para-resumen-de-textos","sections":[{"title":"Crear una línea base sólida","local":"crear-una-linea-base-solida","sections":[],"depth":3}],"depth":2},{"title":"Ajuste fino de mT5 con la API Trainer","local":"ajuste-fino-de-mt5-con-la-api-trainer","sections":[],"depth":2},{"title":"Ajuste fino de mT5 con Keras","local":"ajuste-fino-de-mt5-con-keras","sections":[],"depth":2},{"title":"Ajuste fino de mT5 con 🤗 Accelerate","local":"ajuste-fino-de-mt5-con-accelerate","sections":[{"title":"Preparando todo para el entrenamiento","local":"preparando-todo-para-el-entrenamiento","sections":[],"depth":3},{"title":"Bucle de entrenamiento","local":"bucle-de-entrenamiento","sections":[],"depth":3}],"depth":2},{"title":"Uso de tu modelo ajustado","local":"uso-de-tu-modelo-ajustado","sections":[],"depth":2}],"depth":1}"/><!----> | |
| <link href="/docs/course/pr_1352/es/_app/immutable/assets/0.tn0RQdqM.css" rel="modulepreload"> <!--[--><!--[0--><!--[--><!--[0--><!--[--><p></p> <div class="bg-white leading-none border border-gray-100 rounded-lg flex p-0.5 w-56 text-sm mb-4"><!--[--><a class="flex justify-center flex-1 py-1.5 px-2.5 focus:outline-none !no-underline rounded-l bg-red-50 dark:bg-transparent text-red-600" href="?fw=pt"><!--[--><svg class="mr-1.5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><defs><clipPath id="a"><rect x="3.05" y="0.5" width="25.73" height="31" fill="none"></rect></clipPath></defs><g clip-path="url(#a)"><path d="M24.94,9.51a12.81,12.81,0,0,1,0,18.16,12.68,12.68,0,0,1-18,0,12.81,12.81,0,0,1,0-18.16l9-9V5l-.84.83-6,6a9.58,9.58,0,1,0,13.55,0ZM20.44,9a1.68,1.68,0,1,1,1.67-1.67A1.68,1.68,0,0,1,20.44,9Z" fill="#ee4c2c"></path></g></svg><!--]--> Pytorch</a><a class="flex justify-center flex-1 py-1.5 px-2.5 focus:outline-none !no-underline rounded-r text-gray-500 filter grayscale" href="?fw=tf"><!--[--><svg class="mr-1.5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="0.94em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 274"><path d="M145.726 42.065v42.07l72.861 42.07v-42.07l-72.86-42.07zM0 84.135v42.07l36.43 21.03V105.17L0 84.135zm109.291 21.035l-36.43 21.034v126.2l36.43 21.035v-84.135l36.435 21.035v-42.07l-36.435-21.034V105.17z" fill="#E55B2D"></path><path d="M145.726 42.065L36.43 105.17v42.065l72.861-42.065v42.065l36.435-21.03v-84.14zM255.022 63.1l-36.435 21.035v42.07l36.435-21.035V63.1zm-72.865 84.135l-36.43 21.035v42.07l36.43-21.036v-42.07zm-36.43 63.104l-36.436-21.035v84.135l36.435-21.035V210.34z" fill="#ED8E24"></path><path d="M145.726 0L0 84.135l36.43 21.035l109.296-63.105l72.861 42.07L255.022 63.1L145.726 0zm0 126.204l-36.435 21.03l36.435 21.036l36.43-21.035l-36.43-21.03z" fill="#F8BF3C"></path></svg><!--]--> TensorFlow</a><!--]--></div><!----> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg><!----></button></div> <!--[-1--><!--]--></div><!----> <!--[0--><h1 class="relative group"><a id="resumen-de-textos" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#resumen-de-textos"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Resumen de textos</span></h1><!--]--><!----> <!--[0--><div class="flex space-x-1 absolute z-10 right-0 top-0"><a href="https://discuss.huggingface.co/t/chapter-7-questions" target="_blank"><img alt="Ask a Question" class="!m-0" src="https://img.shields.io/badge/Ask%20a%20question-ffcb4c.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTEgMTA0IDEwNiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMyMzFmMjA7fS5jbHMtMntmaWxsOiNmZmY5YWU7fS5jbHMtM3tmaWxsOiMwMGFlZWY7fS5jbHMtNHtmaWxsOiMwMGE5NGY7fS5jbHMtNXtmaWxsOiNmMTVkMjI7fS5jbHMtNntmaWxsOiNlMzFiMjM7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5EaXNjb3Vyc2VfbG9nbzwvdGl0bGU+PGcgaWQ9IkxheWVyXzIiPjxnIGlkPSJMYXllcl8zIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01MS44NywwQzIzLjcxLDAsMCwyMi44MywwLDUxYzAsLjkxLDAsNTIuODEsMCw1Mi44MWw1MS44Ni0uMDVjMjguMTYsMCw1MS0yMy43MSw1MS01MS44N1M4MCwwLDUxLjg3LDBaIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNTIuMzcsMTkuNzRBMzEuNjIsMzEuNjIsMCwwLDAsMjQuNTgsNjYuNDFsLTUuNzIsMTguNEwzOS40LDgwLjE3YTMxLjYxLDMxLjYxLDAsMSwwLDEzLTYwLjQzWiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTc3LjQ1LDMyLjEyYTMxLjYsMzEuNiwwLDAsMS0zOC4wNSw0OEwxOC44Niw4NC44MmwyMC45MS0yLjQ3QTMxLjYsMzEuNiwwLDAsMCw3Ny40NSwzMi4xMloiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik03MS42MywyNi4yOUEzMS42LDMxLjYsMCwwLDEsMzguOCw3OEwxOC44Niw4NC44MiwzOS40LDgwLjE3QTMxLjYsMzEuNiwwLDAsMCw3MS42MywyNi4yOVoiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0yNi40Nyw2Ny4xMWEzMS42MSwzMS42MSwwLDAsMSw1MS0zNUEzMS42MSwzMS42MSwwLDAsMCwyNC41OCw2Ni40MWwtNS43MiwxOC40WiIvPjxwYXRoIGNsYXNzPSJjbHMtNiIgZD0iTTI0LjU4LDY2LjQxQTMxLjYxLDMxLjYxLDAsMCwxLDcxLjYzLDI2LjI5YTMxLjYxLDMxLjYxLDAsMCwwLTQ5LDM5LjYzbC0zLjc2LDE4LjlaIi8+PC9nPjwvZz48L3N2Zz4="/></a><!----> <!--[0--><a href="https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/en/chapter7/section5_pt.ipynb" target="_blank"><img alt="Open In Colab" class="!m-0" src="https://colab.research.google.com/assets/colab-badge.svg"/></a><!--]--> <!--[0--><a href="https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/en/chapter7/section5_pt.ipynb" target="_blank"><img alt="Open In Studio Lab" class="!m-0" src="https://studiolab.sagemaker.aws/studiolab.svg"/></a><!--]--></div><!--]--> <p>En esta sección veremos cómo se pueden usar los modelos Transformer para condensar documentos largos en resúmenes, una tarea conocida como <em>resumen de textos</em> (<em>text summarization</em>). Esta es una de las tareas de PLN más desafiantes, ya que requiere una variedad de habilidades, como comprender pasajes largos y generar texto coherente que capture los temas principales de un documento. Sin embargo, cuando se hace bien, el resumen de textos es una herramienta poderosa que puede acelerar varios procesos comerciales al aliviar la carga de los expertos de dominio de leer documentos largos en detalle.</p> <iframe class="w-full xl:w-4/6 h-80" src="https://www.youtube-nocookie.com/embed/yHnr5Dk2zCI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><!----> <p>Aunque ya existen varios modelos ajustados para la generación de resúmenes en el <a href="https://huggingface.co/models?pipeline_tag=summarization&sort=downloads" rel="nofollow">Hugging Face Hub</a>, casi todos ellos solo son adecuados para documentos en inglés. Por lo tanto, para agregar un giro en esta sección, entrenaremos un modelo bilingüe para inglés y español. Al final de esta sección, tendrás un <a href="https://huggingface.co/huggingface-course/mt5-small-finetuned-amazon-en-es" rel="nofollow">modelo</a> que puede resumir reseñas de clientes como la que se muestra aquí:</p> <iframe src="https://course-demos-mt5-small-finetuned-amazon-en-es.hf.space" frameborder="0" height="400" title="Gradio app" class="block dark:hidden container p-0 flex-grow space-iframe" allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"></iframe> <p>Como veremos, estos resúmenes son concisos porque se aprenden a partir de los títulos que los clientes proporcionan en sus reseñas de productos. Comencemos reuniendo un corpus bilingüe adecuado para esta tarea.</p> <!--[1--><h2 class="relative group"><a id="preparacion-de-un-corpus-multilingue" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#preparacion-de-un-corpus-multilingue"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Preparación de un corpus multilingüe</span></h2><!--]--><!----> <p>Usaremos el <a href="https://huggingface.co/datasets/amazon_reviews_multi" rel="nofollow">Corpus Multilingüe de Reseñas de Amazon</a> para crear nuestro resumidor bilingüe. Este corpus consta de reseñas de productos de Amazon en seis idiomas y se utiliza habitualmente para evaluar clasificadores multilingües. Sin embargo, dado que cada reseña va acompañada de un título corto, ¡podemos usar los títulos como resúmenes objetivo para que nuestro modelo aprenda de ellos! Para comenzar, descarguemos los subconjuntos en inglés y español del Hugging Face Hub:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> datasets <span class="hljs-keyword">import</span> load_dataset | |
| spanish_dataset = load_dataset(<span class="hljs-string">"amazon_reviews_multi"</span>, <span class="hljs-string">"es"</span>) | |
| english_dataset = load_dataset(<span class="hljs-string">"amazon_reviews_multi"</span>, <span class="hljs-string">"en"</span>) | |
| english_dataset<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->DatasetDict({ | |
| train: Dataset({ | |
| features: [<span class="hljs-string">'review_id'</span>, <span class="hljs-string">'product_id'</span>, <span class="hljs-string">'reviewer_id'</span>, <span class="hljs-string">'stars'</span>, <span class="hljs-string">'review_body'</span>, <span class="hljs-string">'review_title'</span>, <span class="hljs-string">'language'</span>, <span class="hljs-string">'product_category'</span>], | |
| num_rows: <span class="hljs-number">200000</span> | |
| }) | |
| validation: Dataset({ | |
| features: [<span class="hljs-string">'review_id'</span>, <span class="hljs-string">'product_id'</span>, <span class="hljs-string">'reviewer_id'</span>, <span class="hljs-string">'stars'</span>, <span class="hljs-string">'review_body'</span>, <span class="hljs-string">'review_title'</span>, <span class="hljs-string">'language'</span>, <span class="hljs-string">'product_category'</span>], | |
| num_rows: <span class="hljs-number">5000</span> | |
| }) | |
| test: Dataset({ | |
| features: [<span class="hljs-string">'review_id'</span>, <span class="hljs-string">'product_id'</span>, <span class="hljs-string">'reviewer_id'</span>, <span class="hljs-string">'stars'</span>, <span class="hljs-string">'review_body'</span>, <span class="hljs-string">'review_title'</span>, <span class="hljs-string">'language'</span>, <span class="hljs-string">'product_category'</span>], | |
| num_rows: <span class="hljs-number">5000</span> | |
| }) | |
| })<!----></pre></div><!----> <p>Como puedes ver, para cada idioma hay 200,000 reseñas para la división <code>train</code>, y 5,000 reseñas para cada una de las divisiones <code>validation</code> y <code>test</code>. La información de la reseña que nos interesa está contenida en las columnas <code>review_body</code> y <code>review_title</code>. Echemos un vistazo a algunos ejemplos creando una función simple que tome una muestra aleatoria del conjunto de entrenamiento con las técnicas que aprendimos en el <a href="/course/chapter5">Capítulo 5</a>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">def</span> <span class="hljs-title function_">show_samples</span>(<span class="hljs-params">dataset, num_samples=<span class="hljs-number">3</span>, seed=<span class="hljs-number">42</span></span>): | |
| sample = dataset[<span class="hljs-string">"train"</span>].shuffle(seed=seed).select(<span class="hljs-built_in">range</span>(num_samples)) | |
| <span class="hljs-keyword">for</span> example <span class="hljs-keyword">in</span> sample: | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"\n'>> Title: <span class="hljs-subst">{example[<span class="hljs-string">'review_title'</span>]}</span>'"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"'>> Review: <span class="hljs-subst">{example[<span class="hljs-string">'review_body'</span>]}</span>'"</span>) | |
| show_samples(english_dataset)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'>> Title: Worked in front position, not rear'</span> | |
| <span class="hljs-string">'>> Review: 3 stars because these are not rear brakes as stated in the item description. At least the mount adapter only worked on the front fork of the bike that I got it for.'</span> | |
| <span class="hljs-string">'>> Title: meh'</span> | |
| <span class="hljs-string">'>> Review: Does it’s job and it’s gorgeous but mine is falling apart, I had to basically put it together again with hot glue'</span> | |
| <span class="hljs-string">'>> Title: Can\'t beat these for the money'</span> | |
| <span class="hljs-string">'>> Review: Bought this for handling miscellaneous aircraft parts and hanger "stuff" that I needed to organize; it really fit the bill. The unit arrived quickly, was well packaged and arrived intact (always a good sign). There are five wall mounts-- three on the top and two on the bottom. I wanted to mount it on the wall, so all I had to do was to remove the top two layers of plastic drawers, as well as the bottom corner drawers, place it when I wanted and mark it; I then used some of the new plastic screw in wall anchors (the 50 pound variety) and it easily mounted to the wall. Some have remarked that they wanted dividers for the drawers, and that they made those. Good idea. My application was that I needed something that I can see the contents at about eye level, so I wanted the fuller-sized drawers. I also like that these are the new plastic that doesn\'t get brittle and split like my older plastic drawers did. I like the all-plastic construction. It\'s heavy duty enough to hold metal parts, but being made of plastic it\'s not as heavy as a metal frame, so you can easily mount it to the wall and still load it up with heavy stuff, or light stuff. No problem there. For the money, you can\'t beat it. Best one of these I\'ve bought to date-- and I\'ve been using some version of these for over forty years.'</span><!----></pre></div><!----> <blockquote class="tip"><p>✏️ <strong>¡Pruébalo!</strong> Cambia la semilla aleatoria en el comando <code>Dataset.shuffle()</code> para explorar otras reseñas en el corpus. Si hablas español, echa un vistazo a algunas de las reseñas en <code>spanish_dataset</code> para ver si los títulos también parecen resúmenes razonables.</p></blockquote> <p>Esta muestra muestra la diversidad de reseñas que uno encuentra normalmente en línea, que van desde positivas hasta negativas (¡y todo lo demás!). Aunque el ejemplo con el título “meh” no es muy informativo, los otros títulos parecen resúmenes decentes de las reseñas en sí. Entrenar un modelo de resumen en las 400,000 reseñas tomaría demasiado tiempo en una sola GPU, por lo que nos enfocaremos en generar resúmenes para un solo dominio de productos. Para tener una idea de qué dominios podemos elegir, convirtamos <code>english_dataset</code> en un <code>pandas.DataFrame</code> y calculemos el número de reseñas por categoría de producto:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->english_dataset.set_format(<span class="hljs-string">"pandas"</span>) | |
| english_df = english_dataset[<span class="hljs-string">"train"</span>][:] | |
| <span class="hljs-comment"># Mostrar recuentos para los 20 productos principales</span> | |
| english_df[<span class="hljs-string">"product_category"</span>].value_counts()[:<span class="hljs-number">20</span>]<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->home <span class="hljs-number">17679</span> | |
| apparel <span class="hljs-number">15951</span> | |
| wireless <span class="hljs-number">15717</span> | |
| other <span class="hljs-number">13418</span> | |
| beauty <span class="hljs-number">12091</span> | |
| drugstore <span class="hljs-number">11730</span> | |
| kitchen <span class="hljs-number">10382</span> | |
| toy <span class="hljs-number">8745</span> | |
| sports <span class="hljs-number">8277</span> | |
| automotive <span class="hljs-number">7506</span> | |
| lawn_and_garden <span class="hljs-number">7327</span> | |
| home_improvement <span class="hljs-number">7136</span> | |
| pet_products <span class="hljs-number">7082</span> | |
| digital_ebook_purchase <span class="hljs-number">6749</span> | |
| pc <span class="hljs-number">6401</span> | |
| electronics <span class="hljs-number">6186</span> | |
| office_product <span class="hljs-number">5521</span> | |
| shoes <span class="hljs-number">5197</span> | |
| grocery <span class="hljs-number">4730</span> | |
| book <span class="hljs-number">3756</span> | |
| Name: product_category, dtype: int64<!----></pre></div><!----> <p>Los productos más populares en el dataset en inglés son artículos para el hogar, ropa y dispositivos electrónicos inalámbricos. Sin embargo, para mantener el tema de Amazon, concentrémonos en resumir reseñas de libros: después de todo, ¡sobre esto se fundó la empresa! Podemos ver dos categorías de productos que encajan con esto (<code>book</code> y <code>digital_ebook_purchase</code>), así que filtremos los datasets en ambos idiomas para solo estos productos. Como vimos en el <a href="/course/chapter5">Capítulo 5</a>, la función <code>Dataset.filter()</code> nos permite filtrar un dataset de manera muy eficiente, por lo que podemos definir una función simple para hacer esto:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">def</span> <span class="hljs-title function_">filter_books</span>(<span class="hljs-params">example</span>): | |
| <span class="hljs-keyword">return</span> ( | |
| example[<span class="hljs-string">"product_category"</span>] == <span class="hljs-string">"book"</span> | |
| <span class="hljs-keyword">or</span> example[<span class="hljs-string">"product_category"</span>] == <span class="hljs-string">"digital_ebook_purchase"</span> | |
| )<!----></pre></div><!----> <p>Ahora, cuando apliquemos esta función a <code>english_dataset</code> y <code>spanish_dataset</code>, el resultado contendrá solo aquellas filas relacionadas con las categorías de libros. Antes de aplicar el filtro, cambiemos el formato de <code>english_dataset</code> de <code>"pandas"</code> de nuevo a <code>"arrow"</code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->english_dataset.reset_format()<!----></pre></div><!----> <p>Luego podemos aplicar la función de filtrado y, como verificación de cordura, inspeccionemos una muestra de reseñas para ver si efectivamente tratan sobre libros:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->spanish_books = spanish_dataset.<span class="hljs-built_in">filter</span>(filter_books) | |
| english_books = english_dataset.<span class="hljs-built_in">filter</span>(filter_books) | |
| show_samples(english_books)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'>> Title: I\'m dissapointed.'</span> | |
| <span class="hljs-string">'>> Review: I guess I had higher expectations for this book from the reviews. I really thought I\'d at least like it. The plot idea was great. I loved Ash but, it just didnt go anywhere. Most of the book was about their radio show and talking to callers. I wanted the author to dig deeper so we could really get to know the characters. All we know about Grace is that she is attractive looking, Latino and is kind of a brat. I\'m dissapointed.'</span> | |
| <span class="hljs-string">'>> Title: Good art, good price, poor design'</span> | |
| <span class="hljs-string">'>> Review: I had gotten the DC Vintage calendar the past two years, but it was on backorder forever this year and I saw they had shrunk the dimensions for no good reason. This one has good art choices but the design has the fold going through the picture, so it\'s less aesthetically pleasing, especially if you want to keep a picture to hang. For the price, a good calendar'</span> | |
| <span class="hljs-string">'>> Title: Helpful'</span> | |
| <span class="hljs-string">'>> Review: Nearly all the tips useful and. I consider myself an intermediate to advanced user of OneNote. I would highly recommend.'</span><!----></pre></div><!----> <p>Bien, podemos ver que las reseñas no tratan estrictamente sobre libros y pueden referirse a cosas como calendarios y aplicaciones electrónicas como OneNote. Sin embargo, el dominio parece bastante adecuado para entrenar un modelo de resumen. Antes de examinar varios modelos adecuados para esta tarea, nos queda una última tarea de preparación de datos: combinar las reseñas en inglés y español en un único objeto <code>DatasetDict</code>. 🤗 Datasets proporciona una práctica función <code>concatenate_datasets()</code> que (como su nombre indica) apilará dos objetos <code>Dataset</code> uno encima del otro. Por lo tanto, para crear nuestro dataset bilingüe, iteraremos sobre cada división, concatenaremos los datasets para esa división y barajaremos el resultado para asegurarnos de que nuestro modelo no se sobreajuste a un solo idioma:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> datasets <span class="hljs-keyword">import</span> concatenate_datasets, DatasetDict | |
| books_dataset = DatasetDict() | |
| <span class="hljs-keyword">for</span> split <span class="hljs-keyword">in</span> english_books.keys(): | |
| books_dataset[split] = concatenate_datasets( | |
| [english_books[split], spanish_books[split]] | |
| ) | |
| books_dataset[split] = books_dataset[split].shuffle(seed=<span class="hljs-number">42</span>) | |
| <span class="hljs-comment"># Echar un vistazo a algunos ejemplos</span> | |
| show_samples(books_dataset)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'>> Title: Easy to follow!!!!'</span> | |
| <span class="hljs-string">'>> Review: I loved The dash diet weight loss Solution. Never hungry. I would recommend this diet. Also the menus are well rounded. Try it. Has lots of the information need thanks.'</span> | |
| <span class="hljs-string">'>> Title: PARCIALMENTE DAÑADO'</span> | |
| <span class="hljs-string">'>> Review: Me llegó el día que tocaba, junto a otros libros que pedí, pero la caja llegó en mal estado lo cual dañó las esquinas de los libros porque venían sin protección (forro).'</span> | |
| <span class="hljs-string">'>> Title: no lo he podido descargar'</span> | |
| <span class="hljs-string">'>> Review: igual que el anterior'</span><!----></pre></div><!----> <p>¡Esto sin duda parece una mezcla de reseñas en inglés y español! Ahora que tenemos un corpus de entrenamiento, una última cosa a comprobar es la distribución de palabras en las reseñas y sus títulos. Esto es especialmente importante para las tareas de resumen, donde los resúmenes de referencia cortos en los datos pueden sesgar el modelo para que solo genere una o dos palabras en los resúmenes resultantes. Los gráficos a continuación muestran las distribuciones de palabras, y podemos ver que los títulos están fuertemente sesgados hacia solo 1 o 2 palabras:</p> <div class="flex justify-center"><img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter7/review-lengths.svg" alt="Distribuciones de recuento de palabras para los títulos y textos de reseñas."/> <img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter7/review-lengths-dark.svg" alt="Distribuciones de recuento de palabras para los títulos y textos de reseñas."/></div> <p>Para lidiar con esto, filtraremos los ejemplos con títulos muy cortos para que nuestro modelo pueda producir resúmenes más interesantes. Dado que estamos tratando con textos en inglés y español, podemos usar una heurística simple para dividir los títulos por espacios en blanco y luego usar nuestro método <code>Dataset.filter()</code> de la siguiente manera:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->books_dataset = books_dataset.<span class="hljs-built_in">filter</span>(<span class="hljs-keyword">lambda</span> x: <span class="hljs-built_in">len</span>(x[<span class="hljs-string">"review_title"</span>].split()) > <span class="hljs-number">2</span>)<!----></pre></div><!----> <p>Ahora que hemos preparado nuestro corpus, ¡echemos un vistazo a algunos posibles modelos Transformer que se podrían ajustar sobre él!</p> <!--[1--><h2 class="relative group"><a id="modelos-para-resumen-de-textos" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#modelos-para-resumen-de-textos"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Modelos para resumen de textos</span></h2><!--]--><!----> <p>Si lo piensas, el resumen de textos es una tarea similar a la traducción automática: tenemos un cuerpo de texto como una reseña que nos gustaría “traducir” a una versión más corta que capture las características sobresalientes de la entrada. En consecuencia, la mayoría de los modelos Transformer para resumen adoptan la arquitectura de codificador-decodificador que encontramos por primera vez en el <a href="/course/chapter1">Capítulo 1</a>, aunque hay algunas excepciones como la familia de modelos GPT, que también se pueden usar para el resumen en entornos de pocos disparos (<em>few-shot</em>). La siguiente tabla enumera algunos modelos preentrenados populares que se pueden ajustar para resumen.</p> <table><thead><tr><th align="center">Modelo Transformer</th><th>Descripción</th><th align="center">¿Multilingüe?</th></tr></thead><tbody><tr><td align="center"><a href="https://huggingface.co/gpt2-xl" rel="nofollow">GPT-2</a></td><td>Aunque fue entrenado como un modelo de lenguaje autorregresivo, puedes hacer que GPT-2 genere resúmenes agregando “TL;DR” al final del texto de entrada.</td><td align="center">❌</td></tr><tr><td align="center"><a href="https://huggingface.co/google/pegasus-large" rel="nofollow">PEGASUS</a></td><td>Utiliza un objetivo de preentrenamiento para predecir oraciones enmascaradas en textos de varias oraciones. Este objetivo está más cerca del resumen que el modelado de lenguaje estándar y obtiene altas puntuaciones en benchmarks populares.</td><td align="center">❌</td></tr><tr><td align="center"><a href="https://huggingface.co/t5-base" rel="nofollow">T5</a></td><td>Una arquitectura Transformer universal que formula todas las tareas en un marco de texto a texto; por ejemplo, el formato de entrada para que el modelo resuma un documento es <code>summarize: ARTICLE</code>.</td><td align="center">❌</td></tr><tr><td align="center"><a href="https://huggingface.co/google/mt5-base" rel="nofollow">mT5</a></td><td>Una versión multilingüe de T5, preentrenada en el corpus Common Crawl multilingüe (mC4), que cubre 101 idiomas.</td><td align="center">✅</td></tr><tr><td align="center"><a href="https://huggingface.co/facebook/bart-base" rel="nofollow">BART</a></td><td>Una arquitectura Transformer novedosa con una pila de codificador y decodificador entrenada para reconstruir entradas corruptas que combina los esquemas de preentrenamiento de BERT y GPT-2.</td><td align="center">❌</td></tr><tr><td align="center"><a href="https://huggingface.co/facebook/mbart-large-50" rel="nofollow">mBART-50</a></td><td>Una versión multilingüe de BART, preentrenada en 50 idiomas.</td><td align="center">✅</td></tr></tbody></table> <p>Como puedes ver en esta tabla, la mayoría de los modelos Transformer para resumen (y de hecho para la mayoría de las tareas de PLN) son monolingües. Esto es genial si tu tarea está en un idioma de “altos recursos” como el inglés o el alemán, pero menos para los miles de otros idiomas en uso en todo el mundo. Afortunadamente, existe una clase de modelos Transformer multilingües, como mT5 y mBART, que vienen al rescate. Estos modelos están preentrenados mediante modelado de lenguaje, pero con un giro: en lugar de entrenar en un corpus de un solo idioma, ¡se entrenan conjuntamente en textos en más de 50 idiomas a la vez!</p> <p>Nos centraremos en mT5, una arquitectura interesante basada en T5 que fue preentrenada en un marco de texto a texto. En T5, cada tarea de PLN se formula en términos de un prefijo de prompt como <code>summarize:</code>, lo que condiciona al modelo para adaptar el texto generado al prompt. Como se muestra en la siguiente figura, esto hace que T5 sea extremadamente versátil, ¡ya que puedes resolver muchas tareas con un solo modelo!</p> <div class="flex justify-center"><img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter7/t5.svg" alt="Diferentes tareas realizadas por la arquitectura T5."/> <img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter7/t5-dark.svg" alt="Diferentes tareas realizadas por la arquitectura T5."/></div> <p>mT5 no utiliza prefijos, pero comparte gran parte de la versatilidad de T5 y tiene la ventaja de ser multilingüe. Ahora que hemos elegido un modelo, veamos cómo preparar nuestros datos para el entrenamiento.</p> <blockquote class="tip"><p>✏️ <strong>¡Pruébalo!</strong> Una vez que hayas trabajado en esta sección, comprueba cómo se compara mT5 con mBART ajustando este último con las mismas técnicas. Como punto adicional, también puedes intentar ajustar T5 solo con las reseñas en inglés. Dado que T5 tiene un prefijo de prompt especial, deberás anteponer <code>summarize:</code> a los ejemplos de entrada en los pasos de preprocesamiento a continuación.</p></blockquote> <!--[1--><h2 class="relative group"><a id="preprocesamiento-de-los-datos" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#preprocesamiento-de-los-datos"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Preprocesamiento de los datos</span></h2><!--]--><!----> <iframe class="w-full xl:w-4/6 h-80" src="https://www.youtube-nocookie.com/embed/1m7BerpSq8A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><!----> <p>Nuestra siguiente tarea es tokenizar y codificar nuestras reseñas y sus títulos. Como siempre, comenzamos cargando el tokenizador asociado con el punto de control del modelo preentrenado. Usaremos <code>mt5-small</code> como nuestro punto de control para poder ajustar el modelo en una cantidad de tiempo razonable:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoTokenizer | |
| model_checkpoint = <span class="hljs-string">"google/mt5-small"</span> | |
| tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)<!----></pre></div><!----> <blockquote class="tip"><p>💡 En las etapas iniciales de tus proyectos de PLN, una buena práctica es entrenar una clase de modelos “pequeños” en una muestra pequeña de datos. Esto te permite depurar e iterar más rápido hacia un flujo de trabajo de principio a fin. Una vez que estés satisfecho con los resultados, ¡siempre puedes escalar el modelo simplemente cambiando el punto de control del modelo!</p></blockquote> <p>Probemos el tokenizador de mT5 en un pequeño ejemplo:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->inputs = tokenizer(<span class="hljs-string">"I loved reading the Hunger Games!"</span>) | |
| inputs<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{<span class="hljs-string">'input_ids'</span>: [<span class="hljs-number">336</span>, <span class="hljs-number">259</span>, <span class="hljs-number">28387</span>, <span class="hljs-number">11807</span>, <span class="hljs-number">287</span>, <span class="hljs-number">62893</span>, <span class="hljs-number">295</span>, <span class="hljs-number">12507</span>, <span class="hljs-number">1</span>], <span class="hljs-string">'attention_mask'</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>]}<!----></pre></div><!----> <p>Aquí podemos ver los conocidos <code>input_ids</code> y <code>attention_mask</code> que encontramos en nuestros primeros experimentos de ajuste fino en el <a href="/course/chapter3">Capítulo 3</a>. Decodifiquemos estos IDs de entrada con la función <code>convert_ids_to_tokens()</code> del tokenizador para ver con qué tipo de tokenizador estamos tratando:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->tokenizer.convert_ids_to_tokens(inputs.input_ids)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->[<span class="hljs-string">'▁I'</span>, <span class="hljs-string">'▁'</span>, <span class="hljs-string">'loved'</span>, <span class="hljs-string">'▁reading'</span>, <span class="hljs-string">'▁the'</span>, <span class="hljs-string">'▁Hung'</span>, <span class="hljs-string">'er'</span>, <span class="hljs-string">'▁Games'</span>, <span class="hljs-string">'</s>'</span>]<!----></pre></div><!----> <p>El carácter especial Unicode <code>▁</code> y el token de final de secuencia <code></s></code> indican que estamos tratando con el tokenizador SentencePiece, que se basa en el algoritmo de segmentación Unigram discutido en el <a href="/course/chapter6">Capítulo 6</a>. Unigram es especialmente útil para corpus multilingües, ya que permite que SentencePiece sea agnóstico con respecto a los acentos, la puntuación y el hecho de que muchos idiomas, como el japonés, no tienen caracteres de espacio en blanco.</p> <p>Para tokenizar nuestro corpus, tenemos que lidiar con una sutileza asociada con el resumen: debido a que nuestras etiquetas también son texto, es posible que excedan el tamaño de contexto máximo del modelo. Esto significa que necesitamos aplicar truncamiento tanto a las reseñas como a sus títulos para asegurarnos de no pasar entradas excesivamente largas a nuestro modelo. Los tokenizadores en 🤗 Transformers proporcionan un práctico argumento <code>text_target</code> que te permite tokenizar las etiquetas en paralelo a las entradas. Aquí hay un ejemplo de cómo se procesan las entradas y los objetivos para mT5:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->max_input_length = <span class="hljs-number">512</span> | |
| max_target_length = <span class="hljs-number">30</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">preprocess_function</span>(<span class="hljs-params">examples</span>): | |
| model_inputs = tokenizer( | |
| examples[<span class="hljs-string">"review_body"</span>], | |
| max_length=max_input_length, | |
| truncation=<span class="hljs-literal">True</span>, | |
| ) | |
| labels = tokenizer( | |
| examples[<span class="hljs-string">"review_title"</span>], max_length=max_target_length, truncation=<span class="hljs-literal">True</span> | |
| ) | |
| model_inputs[<span class="hljs-string">"labels"</span>] = labels[<span class="hljs-string">"input_ids"</span>] | |
| <span class="hljs-keyword">return</span> model_inputs<!----></pre></div><!----> <p>Repasemos este código para entender qué está sucediendo. Lo primero que hemos hecho es definir valores para <code>max_input_length</code> y <code>max_target_length</code>, que establecen los límites superiores de longitud para nuestras reseñas y títulos. Dado que el cuerpo de la reseña suele ser mucho más extenso que el título, hemos escalado estos valores en consecuencia.</p> <p>Con <code>preprocess_function()</code>, luego es una cuestión sencilla tokenizar todo el corpus utilizando la práctica función <code>Dataset.map()</code> que hemos usado ampliamente a lo largo de este curso:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->tokenized_datasets = books_dataset.<span class="hljs-built_in">map</span>(preprocess_function, batched=<span class="hljs-literal">True</span>)<!----></pre></div><!----> <p>Ahora que el corpus ha sido preprocesado, echemos un vistazo a algunas métricas que se utilizan habitualmente para el resumen. Como veremos, no existe una solución mágica a la hora de medir la calidad del texto generado por máquinas.</p> <blockquote class="tip"><p>💡 Es posible que hayas notado que usamos <code>batched=True</code> en nuestra función <code>Dataset.map()</code> anterior. Esto codifica los ejemplos en lotes de 1,000 (el valor predeterminado) y te permite hacer uso de las capacidades de subprocesamiento múltiple de los tokenizadores rápidos en 🤗 Transformers. ¡Siempre que sea posible, intenta usar <code>batched=True</code> para aprovechar al máximo tu preprocesamiento!</p></blockquote> <!--[1--><h2 class="relative group"><a id="metricas-para-resumen-de-textos" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#metricas-para-resumen-de-textos"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Métricas para resumen de textos</span></h2><!--]--><!----> <iframe class="w-full xl:w-4/6 h-80" src="https://www.youtube-nocookie.com/embed/TMshhnrEXlg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><!----> <p>En comparación con la mayoría de las otras tareas que hemos cubierto en este curso, medir el rendimiento de las tareas de generación de texto como el resumen o la traducción no es tan sencillo. Por ejemplo, dada una reseña como “I loved reading the Hunger Games”, existen múltiples resúmenes válidos, como “I loved the Hunger Games” o “Hunger Games is a great read”. Claramente, aplicar algún tipo de coincidencia exacta entre el resumen generado y la etiqueta no es una buena solución; incluso los humanos obtendrían malos resultados con dicha métrica, porque todos tenemos nuestro propio estilo de escritura.</p> <p>Para el resumen, una de las métricas más utilizadas es la <a href="https://en.wikipedia.org/wiki/ROUGE_(metric)" rel="nofollow">puntuación ROUGE</a> (abreviatura de <em>Recall-Oriented Understudy for Gisting Evaluation</em>). La idea básica detrás de esta métrica es comparar un resumen generado con un conjunto de resúmenes de referencia que normalmente son creados por humanos. Para hacer esto más preciso, supongamos que queremos comparar los dos resúmenes siguientes:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->generated_summary = <span class="hljs-string">"I absolutely loved reading the Hunger Games"</span> | |
| reference_summary = <span class="hljs-string">"I loved reading the Hunger Games"</span><!----></pre></div><!----> <p>Una forma de compararlos podría ser contar el número de palabras superpuestas, que en este caso sería 6. Sin embargo, esto es un poco rudimentario, por lo que ROUGE se basa en calcular las puntuaciones de <em>precisión</em> (<em>precision</em>) y <em>exhaustividad</em> (<em>recall</em>) para la superposición.</p> <blockquote class="tip"><p>🙋 No te preocupes si esta es la primera vez que escuchas sobre precisión y exhaustividad: repasaremos algunos ejemplos explícitos juntos para que todo quede claro. Estas métricas se suelen encontrar en tareas de clasificación, por lo que si deseas comprender cómo se definen en ese contexto, te recomendamos consultar las <a href="https://scikit-learn.org/stable/auto_examples/model_selection/plot_precision_recall.html" rel="nofollow">guías</a> de <code>scikit-learn</code>.</p></blockquote> <p>Para ROUGE, la exhaustividad mide qué parte del resumen de referencia es capturada por el generado. Si solo estamos comparando palabras, la exhaustividad se puede calcular de acuerdo con la siguiente fórmula: <!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mi mathvariant="normal">R</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">l</mi></mrow><mo>=</mo><mfrac><mrow><mi mathvariant="normal">N</mi><mover accent="true"><mi mathvariant="normal">u</mi><mo>ˊ</mo></mover><mi mathvariant="normal">m</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">o</mi><mtext> </mtext><mi mathvariant="normal">d</mi><mi mathvariant="normal">e</mi><mtext> </mtext><mi mathvariant="normal">p</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi><mtext> </mtext><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi></mrow><mrow><mi mathvariant="normal">N</mi><mover accent="true"><mi mathvariant="normal">u</mi><mo>ˊ</mo></mover><mi mathvariant="normal">m</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">o</mi><mtext> </mtext><mi mathvariant="normal">t</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mtext> </mtext><mi mathvariant="normal">d</mi><mi mathvariant="normal">e</mi><mtext> </mtext><mi mathvariant="normal">p</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi><mtext> </mtext><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mtext> </mtext><mi mathvariant="normal">e</mi><mi mathvariant="normal">l</mi><mtext> </mtext><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">m</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mtext> </mtext><mi mathvariant="normal">d</mi><mi mathvariant="normal">e</mi><mtext> </mtext><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">f</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">a</mi></mrow></mfrac></mrow><annotation encoding="application/x-tex"> \mathrm{Recall} = \frac{\mathrm{Número\,de\,palabras\,superpuestas}}{\mathrm{Número\,total\,de\,palabras\,en\,el\,resumen\,de\,referencia}} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">Recall</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2519em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">N</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathrm">u</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord mathrm">ˊ</span></span></span></span></span></span></span><span class="mord mathrm">mero</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">total</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">de</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">palabras</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">en</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">el</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">resumen</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">de</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">referencia</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">N</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathrm">u</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord mathrm">ˊ</span></span></span></span></span></span></span><span class="mord mathrm">mero</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">de</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">palabras</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">superpuestas</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></p> <p>Para nuestro ejemplo simple anterior, esta fórmula da una exhaustividad perfecta de 6/6 = 1; es decir, todas las palabras en el resumen de referencia han sido producidas por el modelo. Esto puede sonar genial, pero imagina si nuestro resumen generado hubiera sido “I really really loved reading the Hunger Games all night”. Esto también tendría una exhaustividad perfecta, pero podría decirse que es un peor resumen ya que es redundante. Para lidiar con estos escenarios también calculamos la precisión, que en el contexto de ROUGE mide qué parte del resumen generado fue relevante: <!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">n</mi></mrow><mo>=</mo><mfrac><mrow><mi mathvariant="normal">N</mi><mover accent="true"><mi mathvariant="normal">u</mi><mo>ˊ</mo></mover><mi mathvariant="normal">m</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">o</mi><mtext> </mtext><mi mathvariant="normal">d</mi><mi mathvariant="normal">e</mi><mtext> </mtext><mi mathvariant="normal">p</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi><mtext> </mtext><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi></mrow><mrow><mi mathvariant="normal">N</mi><mover accent="true"><mi mathvariant="normal">u</mi><mo>ˊ</mo></mover><mi mathvariant="normal">m</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">o</mi><mtext> </mtext><mi mathvariant="normal">t</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mtext> </mtext><mi mathvariant="normal">d</mi><mi mathvariant="normal">e</mi><mtext> </mtext><mi mathvariant="normal">p</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi><mtext> </mtext><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mtext> </mtext><mi mathvariant="normal">e</mi><mi mathvariant="normal">l</mi><mtext> </mtext><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">m</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mtext> </mtext><mi mathvariant="normal">g</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">d</mi><mi mathvariant="normal">o</mi></mrow></mfrac></mrow><annotation encoding="application/x-tex"> \mathrm{Precision} = \frac{\mathrm{Número\,de\,palabras\,superpuestas}}{\mathrm{Número\,total\,de\,palabras\,en\,el\,resumen\,generado}} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Precision</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2519em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">N</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathrm">u</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord mathrm">ˊ</span></span></span></span></span></span></span><span class="mord mathrm">mero</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">total</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">de</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">palabras</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">en</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">el</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">resumen</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">generado</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">N</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathrm">u</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord mathrm">ˊ</span></span></span></span></span></span></span><span class="mord mathrm">mero</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">de</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">palabras</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">superpuestas</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></p> <p>Aplicar esto a nuestro resumen redundante da una precisión de 6/10 = 0.6, que es considerablemente peor que la precisión de 6/7 = 0.86 obtenida por nuestro resumen más corto. En la práctica, normalmente se calculan tanto la precisión como la exhaustividad, y luego se informa la puntuación F1 (la media armónica de precisión y exhaustividad). Podemos hacer esto fácilmente en 🤗 Datasets instalando primero el paquete <code>rouge_score</code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-py "><!---->!pip install rouge_score<!----></pre></div><!----> <p>y luego cargando la métrica ROUGE de la siguiente manera:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">import</span> evaluate | |
| rouge_score = evaluate.load(<span class="hljs-string">"rouge"</span>)<!----></pre></div><!----> <p>Luego podemos usar la función <code>rouge_score.compute()</code> para calcular todas las métricas a la vez:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->scores = rouge_score.compute( | |
| predictions=[generated_summary], references=[reference_summary] | |
| ) | |
| scores<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{<span class="hljs-string">'rouge1'</span>: AggregateScore(low=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>), mid=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>), high=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>)), | |
| <span class="hljs-string">'rouge2'</span>: AggregateScore(low=Score(precision=<span class="hljs-number">0.67</span>, recall=<span class="hljs-number">0.8</span>, fmeasure=<span class="hljs-number">0.73</span>), mid=Score(precision=<span class="hljs-number">0.67</span>, recall=<span class="hljs-number">0.8</span>, fmeasure=<span class="hljs-number">0.73</span>), high=Score(precision=<span class="hljs-number">0.67</span>, recall=<span class="hljs-number">0.8</span>, fmeasure=<span class="hljs-number">0.73</span>)), | |
| <span class="hljs-string">'rougeL'</span>: AggregateScore(low=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>), mid=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>), high=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>)), | |
| <span class="hljs-string">'rougeLsum'</span>: AggregateScore(low=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>), mid=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>), high=Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>))}<!----></pre></div><!----> <p>¡Vaya, hay mucha información en esa salida! ¿Qué significa todo esto? Primero, 🤗 Datasets en realidad calcula intervalos de confianza para precisión, exhaustividad y puntuación F1; estos son los atributos <code>low</code>, <code>mid</code> y <code>high</code> que puedes ver aquí. Además, 🤗 Datasets calcula una variedad de puntuaciones ROUGE que se basan en diferentes tipos de granularidad de texto al comparar los resúmenes generados y de referencia. La variante <code>rouge1</code> es la superposición de unigramas: esta es solo una forma elegante de decir la superposición de palabras y es exactamente la métrica que hemos discutido anteriormente. Para verificar esto, extraigamos el valor <code>mid</code> de nuestras puntuaciones:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->scores[<span class="hljs-string">"rouge1"</span>].mid<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->Score(precision=<span class="hljs-number">0.86</span>, recall=<span class="hljs-number">1.0</span>, fmeasure=<span class="hljs-number">0.92</span>)<!----></pre></div><!----> <p>¡Genial, los números de precisión y exhaustividad coinciden! Ahora, ¿qué pasa con esas otras puntuaciones ROUGE? <code>rouge2</code> mide la superposición entre bigramas (piensa en la superposición de pares de palabras), mientras que <code>rougeL</code> y <code>rougeLsum</code> miden las secuencias coincidentes más largas de palabras buscando las subsecuencias comunes más largas en los resúmenes generados y de referencia. El “sum” en <code>rougeLsum</code> se refiere al hecho de que esta métrica se calcula sobre un resumen completo, mientras que <code>rougeL</code> se calcula como el promedio sobre oraciones individuales.</p> <blockquote class="tip"><p>✏️ <strong>¡Pruébalo!</strong> Crea tu propio ejemplo de un resumen generado y de referencia y comprueba si las puntuaciones ROUGE resultantes coinciden con un cálculo manual basado en las fórmulas de precisión y exhaustividad. Para puntos adicionales, divide el texto en bigramas y compara la precisión y la exhaustividad para la métrica <code>rouge2</code>.</p></blockquote> <p>Usaremos estas puntuaciones ROUGE para rastrear el rendimiento de nuestro modelo, pero antes de hacerlo hagamos algo que todo buen profesional de PLN debería hacer: ¡crear una línea base sólida y sencilla!</p> <!--[2--><h3 class="relative group"><a id="crear-una-linea-base-solida" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#crear-una-linea-base-solida"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Crear una línea base sólida</span></h3><!--]--><!----> <p>Una línea base común para el resumen de textos es simplemente tomar las tres primeras oraciones de un artículo, a menudo llamada la línea base <em>lead-3</em>. Podríamos usar puntos para rastrear los límites de las oraciones, pero esto fallará con acrónimos como “U.S.” o “U.N.”, por lo que usaremos la biblioteca <code>nltk</code>, que incluye un algoritmo más robusto para manejar estos casos. Puedes instalar el paquete usando <code>pip</code> de la siguiente manera:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->!pip install nltk<!----></pre></div><!----> <p>y luego descargar las reglas de puntuación:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">import</span> nltk | |
| nltk.download(<span class="hljs-string">"punkt"</span>)<!----></pre></div><!----> <p>A continuación, importamos el tokenizador de oraciones de <code>nltk</code> y creamos una función simple para extraer las primeras tres oraciones en una reseña. La convención en el resumen de textos es separar cada oración del resumen con un salto de línea, así que incluyamos esto también y probémoslo en un ejemplo de entrenamiento:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> nltk.tokenize <span class="hljs-keyword">import</span> sent_tokenize | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">three_sentence_summary</span>(<span class="hljs-params">text</span>): | |
| <span class="hljs-keyword">return</span> <span class="hljs-string">"\n"</span>.join(sent_tokenize(text)[:<span class="hljs-number">3</span>]) | |
| <span class="hljs-built_in">print</span>(three_sentence_summary(books_dataset[<span class="hljs-string">"train"</span>][<span class="hljs-number">1</span>][<span class="hljs-string">"review_body"</span>]))<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'I grew up reading Koontz, and years ago, I stopped,convinced i had "outgrown" him.'</span> | |
| <span class="hljs-string">'Still,when a friend was looking for something suspenseful too read, I suggested Koontz.'</span> | |
| <span class="hljs-string">'She found Strangers.'</span><!----></pre></div><!----> <p>Esto parece funcionar, así que implementemos ahora una función que extraiga estos “resúmenes” de un dataset y calcule las puntuaciones ROUGE para la línea base:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">def</span> <span class="hljs-title function_">evaluate_baseline</span>(<span class="hljs-params">dataset, metric</span>): | |
| summaries = [three_sentence_summary(text) <span class="hljs-keyword">for</span> text <span class="hljs-keyword">in</span> dataset[<span class="hljs-string">"review_body"</span>]] | |
| <span class="hljs-keyword">return</span> metric.compute(predictions=summaries, references=dataset[<span class="hljs-string">"review_title"</span>])<!----></pre></div><!----> <p>Luego podemos usar esta función para calcular las puntuaciones ROUGE sobre el conjunto de validación y formatearlas un poco con Pandas:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd | |
| score = evaluate_baseline(books_dataset[<span class="hljs-string">"validation"</span>], rouge_score) | |
| rouge_names = [<span class="hljs-string">"rouge1"</span>, <span class="hljs-string">"rouge2"</span>, <span class="hljs-string">"rougeL"</span>, <span class="hljs-string">"rougeLsum"</span>] | |
| rouge_dict = <span class="hljs-built_in">dict</span>((rn, <span class="hljs-built_in">round</span>(score[rn].mid.fmeasure * <span class="hljs-number">100</span>, <span class="hljs-number">2</span>)) <span class="hljs-keyword">for</span> rn <span class="hljs-keyword">in</span> rouge_names) | |
| rouge_dict<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">16.74</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">8.83</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">15.6</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">15.96</span>}<!----></pre></div><!----> <p>Podemos ver que la puntuación <code>rouge2</code> es significativamente más baja que el resto; esto probablemente refleja el hecho de que los títulos de las reseñas suelen ser concisos y, por lo tanto, la línea base lead-3 es demasiado extensa. Ahora que tenemos una buena línea base desde la cual trabajar, ¡centremos nuestra atención en ajustar mT5!</p> <!--[0--><!--[1--><h2 class="relative group"><a id="ajuste-fino-de-mt5-con-la-api-trainer" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#ajuste-fino-de-mt5-con-la-api-trainer"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Ajuste fino de mT5 con la API Trainer</span></h2><!--]--><!----> <p>Ajustar un modelo para resumen es muy similar a las otras tareas que hemos cubierto en este capítulo. Lo primero que debemos hacer es cargar el modelo preentrenado desde el punto de control <code>mt5-small</code>. Dado que el resumen es una tarea de secuencia a secuencia, podemos cargar el modelo con la clase <code>AutoModelForSeq2SeqLM</code>, que descargará y almacenará en caché los pesos automáticamente:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoModelForSeq2SeqLM | |
| model = AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint)<!----></pre></div><!----><!--]--> <blockquote class="tip"><p>💡 Si te preguntas por qué no ves ninguna advertencia sobre ajustar el modelo en una tarea posterior, es porque para las tareas de secuencia a secuencia mantenemos todos los pesos de la red. Compara esto con nuestro modelo de clasificación de texto en el <a href="/course/chapter3">Capítulo 3</a>, donde el cabezal del modelo preentrenado fue reemplazado por una red inicializada aleatoriamente.</p></blockquote> <p>Lo siguiente que debemos hacer es iniciar sesión en el Hugging Face Hub. Si estás ejecutando este código en un notebook, puedes hacerlo con la siguiente función de utilidad:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> huggingface_hub <span class="hljs-keyword">import</span> notebook_login | |
| notebook_login()<!----></pre></div><!----> <p>que mostrará un widget donde podrás ingresar tus credenciales. Alternativamente, puedes ejecutar este comando en tu terminal e iniciar sesión allí:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class=" "><!---->huggingface-<span class="hljs-keyword">cli</span> login<!----></pre></div><!----> <!--[0--><p>Necesitaremos generar resúmenes para calcular las puntuaciones ROUGE durante el entrenamiento. Afortunadamente, 🤗 Transformers proporciona las clases dedicadas <code>Seq2SeqTrainingArguments</code> y <code>Seq2SeqTrainer</code> que pueden hacer esto por nosotros automáticamente. Para ver cómo funciona, primero definamos los hiperparámetros y otros argumentos para nuestros experimentos:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> Seq2SeqTrainingArguments | |
| batch_size = <span class="hljs-number">8</span> | |
| num_train_epochs = <span class="hljs-number">8</span> | |
| <span class="hljs-comment"># Mostrar la pérdida de entrenamiento con cada época</span> | |
| logging_steps = <span class="hljs-built_in">len</span>(tokenized_datasets[<span class="hljs-string">"train"</span>]) // batch_size | |
| model_name = model_checkpoint.split(<span class="hljs-string">"/"</span>)[-<span class="hljs-number">1</span>] | |
| args = Seq2SeqTrainingArguments( | |
| output_dir=<span class="hljs-string">f"<span class="hljs-subst">{model_name}</span>-finetuned-amazon-en-es"</span>, | |
| evaluation_strategy=<span class="hljs-string">"epoch"</span>, | |
| learning_rate=<span class="hljs-number">5.6e-5</span>, | |
| per_device_train_batch_size=batch_size, | |
| per_device_eval_batch_size=batch_size, | |
| weight_decay=<span class="hljs-number">0.01</span>, | |
| save_total_limit=<span class="hljs-number">3</span>, | |
| num_train_epochs=num_train_epochs, | |
| predict_with_generate=<span class="hljs-literal">True</span>, | |
| logging_steps=logging_steps, | |
| push_to_hub=<span class="hljs-literal">True</span>, | |
| )<!----></pre></div><!----> <p>Aquí, el argumento <code>predict_with_generate</code> se ha establecido para indicar que debemos generar resúmenes durante la evaluación para que podamos calcular las puntuaciones ROUGE para cada época. Como se discutió en el <a href="/course/chapter1">Capítulo 1</a>, el decodificador realiza la inferencia prediciendo tokens uno por uno, y esto se implementa mediante el método <code>generate()</code> del modelo. Establecer <code>predict_with_generate=True</code> le indica al <code>Seq2SeqTrainer</code> que use ese método para la evaluación. También hemos ajustado algunos de los hiperparámetros predeterminados, como la tasa de aprendizaje, el número de épocas y el decaimiento de pesos, y hemos configurado la opción <code>save_total_limit</code> para guardar solo hasta 3 puntos de control durante el entrenamiento; esto se debe a que incluso la versión “pequeña” de mT5 usa alrededor de un GB de espacio en el disco duro, y podemos ahorrar algo de espacio limitando el número de copias que guardamos.</p> <p>El argumento <code>push_to_hub=True</code> nos permitirá subir el modelo al Hub después del entrenamiento; encontrarás el repositorio bajo tu perfil de usuario en la ubicación definida por <code>output_dir</code>. Ten en cuenta que puedes especificar el nombre del repositorio al que deseas subir con el argumento <code>hub_model_id</code> (en particular, deberás usar este argumento para subirlo a una organización). Por ejemplo, cuando subimos el modelo a la <a href="https://huggingface.co/huggingface-course" rel="nofollow">organización <code>huggingface-course</code></a>, agregamos <code>hub_model_id="huggingface-course/mt5-finetuned-amazon-en-es"</code> a <code>Seq2SeqTrainingArguments</code>.</p> <p>Lo siguiente que debemos hacer es proporcionar al entrenador una función <code>compute_metrics()</code> para que podamos evaluar nuestro modelo durante el entrenamiento. Para el resumen, esto es un poco más complejo que simplemente llamar a <code>rouge_score.compute()</code> sobre las predicciones del modelo, ya que necesitamos <em>decodificar</em> las salidas y etiquetas en texto antes de poder calcular las puntuaciones ROUGE. La siguiente función hace exactamente eso, y también utiliza la función <code>sent_tokenize()</code> de <code>nltk</code> para separar las oraciones de resumen con saltos de línea:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">compute_metrics</span>(<span class="hljs-params">eval_pred</span>): | |
| predictions, labels = eval_pred | |
| <span class="hljs-comment"># Decodificar resúmenes generados en texto</span> | |
| decoded_preds = tokenizer.batch_decode(predictions, skip_special_tokens=<span class="hljs-literal">True</span>) | |
| <span class="hljs-comment"># Reemplazar -100 en las etiquetas ya que no podemos decodificarlas</span> | |
| labels = np.where(labels != -<span class="hljs-number">100</span>, labels, tokenizer.pad_token_id) | |
| <span class="hljs-comment"># Decodificar resúmenes de referencia en texto</span> | |
| decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=<span class="hljs-literal">True</span>) | |
| <span class="hljs-comment"># ROUGE espera un salto de línea después de cada oración</span> | |
| decoded_preds = [<span class="hljs-string">"\n"</span>.join(sent_tokenize(pred.strip())) <span class="hljs-keyword">for</span> pred <span class="hljs-keyword">in</span> decoded_preds] | |
| decoded_labels = [<span class="hljs-string">"\n"</span>.join(sent_tokenize(label.strip())) <span class="hljs-keyword">for</span> label <span class="hljs-keyword">in</span> decoded_labels] | |
| <span class="hljs-comment"># Calcular puntuaciones ROUGE</span> | |
| result = rouge_score.compute( | |
| predictions=decoded_preds, references=decoded_labels, use_stemmer=<span class="hljs-literal">True</span> | |
| ) | |
| <span class="hljs-comment"># Extraer las puntuaciones medianas</span> | |
| result = {key: value.mid.fmeasure * <span class="hljs-number">100</span> <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> result.items()} | |
| <span class="hljs-keyword">return</span> {k: <span class="hljs-built_in">round</span>(v, <span class="hljs-number">4</span>) <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> result.items()}<!----></pre></div><!----><!--]--> <p>A continuación, necesitamos definir un collator de datos para nuestra tarea de secuencia a secuencia. Dado que mT5 es un modelo Transformer de codificador-decodificador, una sutileza al preparar nuestros lotes es que durante la decodificación necesitamos desplazar las etiquetas a la derecha en una posición. Esto es necesario para garantizar que el decodificador solo vea las etiquetas reales anteriores y no las actuales o futuras, lo que facilitaría que el modelo memorizara. Esto es similar a cómo se aplica la autoatención enmascarada a las entradas en una tarea como el <a href="/course/chapter7/6">modelado de lenguaje causal</a>.</p> <p>Afortunadamente, 🤗 Transformers proporciona un collator <code>DataCollatorForSeq2Seq</code> que rellenará dinámicamente las entradas y las etiquetas por nosotros. Para crear este collator, simplemente necesitamos proporcionar el <code>tokenizer</code> y el <code>model</code>:</p> <!--[0--><div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> DataCollatorForSeq2Seq | |
| data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)<!----></pre></div><!--]--> <p>Veamos qué produce este collator cuando se le alimenta con un pequeño lote de ejemplos. Primero, necesitamos eliminar las columnas con cadenas de texto porque el collator no sabrá cómo rellenar estos elementos:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->tokenized_datasets = tokenized_datasets.remove_columns( | |
| books_dataset[<span class="hljs-string">"train"</span>].column_names | |
| )<!----></pre></div><!----> <p>Dado que el collator espera una lista de <code>dict</code>s, donde cada <code>dict</code> representa un solo ejemplo en el dataset, también necesitamos transformar los datos al formato esperado antes de pasarlos al collator de datos:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->features = [tokenized_datasets[<span class="hljs-string">"train"</span>][i] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">2</span>)] | |
| data_collator(features)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{<span class="hljs-string">'attention_mask'</span>: tensor([[<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, | |
| <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], | |
| [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, | |
| <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>]]), <span class="hljs-string">'input_ids'</span>: tensor([[ <span class="hljs-number">1494</span>, <span class="hljs-number">259</span>, <span class="hljs-number">8622</span>, <span class="hljs-number">390</span>, <span class="hljs-number">259</span>, <span class="hljs-number">262</span>, <span class="hljs-number">2316</span>, <span class="hljs-number">3435</span>, <span class="hljs-number">955</span>, | |
| <span class="hljs-number">772</span>, <span class="hljs-number">281</span>, <span class="hljs-number">772</span>, <span class="hljs-number">1617</span>, <span class="hljs-number">263</span>, <span class="hljs-number">305</span>, <span class="hljs-number">14701</span>, <span class="hljs-number">260</span>, <span class="hljs-number">1385</span>, | |
| <span class="hljs-number">3031</span>, <span class="hljs-number">259</span>, <span class="hljs-number">24146</span>, <span class="hljs-number">332</span>, <span class="hljs-number">1037</span>, <span class="hljs-number">259</span>, <span class="hljs-number">43906</span>, <span class="hljs-number">305</span>, <span class="hljs-number">336</span>, | |
| <span class="hljs-number">260</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], | |
| [ <span class="hljs-number">259</span>, <span class="hljs-number">27531</span>, <span class="hljs-number">13483</span>, <span class="hljs-number">259</span>, <span class="hljs-number">7505</span>, <span class="hljs-number">260</span>, <span class="hljs-number">112240</span>, <span class="hljs-number">15192</span>, <span class="hljs-number">305</span>, | |
| <span class="hljs-number">53198</span>, <span class="hljs-number">276</span>, <span class="hljs-number">259</span>, <span class="hljs-number">74060</span>, <span class="hljs-number">263</span>, <span class="hljs-number">260</span>, <span class="hljs-number">459</span>, <span class="hljs-number">25640</span>, <span class="hljs-number">776</span>, | |
| <span class="hljs-number">2119</span>, <span class="hljs-number">336</span>, <span class="hljs-number">259</span>, <span class="hljs-number">2220</span>, <span class="hljs-number">259</span>, <span class="hljs-number">18896</span>, <span class="hljs-number">288</span>, <span class="hljs-number">4906</span>, <span class="hljs-number">288</span>, | |
| <span class="hljs-number">1037</span>, <span class="hljs-number">3931</span>, <span class="hljs-number">260</span>, <span class="hljs-number">7083</span>, <span class="hljs-number">101476</span>, <span class="hljs-number">1143</span>, <span class="hljs-number">260</span>, <span class="hljs-number">1</span>]]), <span class="hljs-string">'labels'</span>: tensor([[ <span class="hljs-number">7483</span>, <span class="hljs-number">259</span>, <span class="hljs-number">2364</span>, <span class="hljs-number">15695</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">100</span>], | |
| [ <span class="hljs-number">259</span>, <span class="hljs-number">27531</span>, <span class="hljs-number">13483</span>, <span class="hljs-number">259</span>, <span class="hljs-number">7505</span>, <span class="hljs-number">1</span>]]), <span class="hljs-string">'decoder_input_ids'</span>: tensor([[ <span class="hljs-number">0</span>, <span class="hljs-number">7483</span>, <span class="hljs-number">259</span>, <span class="hljs-number">2364</span>, <span class="hljs-number">15695</span>, <span class="hljs-number">1</span>], | |
| [ <span class="hljs-number">0</span>, <span class="hljs-number">259</span>, <span class="hljs-number">27531</span>, <span class="hljs-number">13483</span>, <span class="hljs-number">259</span>, <span class="hljs-number">7505</span>]])}<!----></pre></div><!----> <p>Lo principal a tener en cuenta aquí es que el primer ejemplo es más largo que el segundo, por lo que los <code>input_ids</code> y la <code>attention_mask</code> del segundo ejemplo se han rellenado a la derecha con un token <code>[PAD]</code> (cuyo ID es <code>0</code>). De manera similar, podemos ver que los <code>labels</code> se han rellenado con valores <code>-100</code>, para asegurarse de que los tokens de relleno sean ignorados por la función de pérdida. Y finalmente, podemos ver un nuevo <code>decoder_input_ids</code> que ha desplazado las etiquetas a la derecha insertando un token <code>[PAD]</code> en la primera entrada.</p> <!--[0--><p>¡Finalmente tenemos todos los ingredientes que necesitamos para entrenar! Ahora simplemente necesitamos instanciar el entrenador con los argumentos estándar:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> Seq2SeqTrainer | |
| trainer = Seq2SeqTrainer( | |
| model, | |
| args, | |
| train_dataset=tokenized_datasets[<span class="hljs-string">"train"</span>], | |
| eval_dataset=tokenized_datasets[<span class="hljs-string">"validation"</span>], | |
| data_collator=data_collator, | |
| tokenizer=tokenizer, | |
| compute_metrics=compute_metrics, | |
| )<!----></pre></div><!----> <p>y lanzar nuestra ejecución de entrenamiento:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->trainer.train()<!----></pre></div><!----> <p>Durante el entrenamiento, deberías ver disminuir la pérdida de entrenamiento y aumentar las puntuaciones ROUGE con cada época. Una vez que se complete el entrenamiento, puedes ver las puntuaciones ROUGE finales ejecutando <code>Trainer.evaluate()</code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->trainer.evaluate()<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{<span class="hljs-string">'eval_loss'</span>: <span class="hljs-number">3.028524398803711</span>, | |
| <span class="hljs-string">'eval_rouge1'</span>: <span class="hljs-number">16.9728</span>, | |
| <span class="hljs-string">'eval_rouge2'</span>: <span class="hljs-number">8.2969</span>, | |
| <span class="hljs-string">'eval_rougeL'</span>: <span class="hljs-number">16.8366</span>, | |
| <span class="hljs-string">'eval_rougeLsum'</span>: <span class="hljs-number">16.851</span>, | |
| <span class="hljs-string">'eval_gen_len'</span>: <span class="hljs-number">10.1597</span>, | |
| <span class="hljs-string">'eval_runtime'</span>: <span class="hljs-number">6.1054</span>, | |
| <span class="hljs-string">'eval_samples_per_second'</span>: <span class="hljs-number">38.982</span>, | |
| <span class="hljs-string">'eval_steps_per_second'</span>: <span class="hljs-number">4.914</span>}<!----></pre></div><!----> <p>A partir de las puntuaciones podemos ver que nuestro modelo ha superado cómodamente a nuestra línea base lead-3, ¡genial! Lo último que debemos hacer es subir los pesos del modelo al Hub, de la siguiente manera:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class=" "><!---->trainer.push_to_hub(<span class="hljs-attribute">commit_message</span>=<span class="hljs-string">"Training complete"</span>, <span class="hljs-attribute">tags</span>=<span class="hljs-string">"summarization"</span>)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'https://huggingface.co/huggingface-course/mt5-finetuned-amazon-en-es/commit/aa0536b829b28e73e1e4b94b8a5aacec420d40e0'</span><!----></pre></div><!----> <p>Esto guardará el punto de control y los archivos de configuración en <code>output_dir</code>, antes de subir todos los archivos al Hub. Al especificar el argumento <code>tags</code>, también nos aseguramos de que el widget en el Hub sea uno para un pipeline de resumen en lugar del de generación de texto predeterminado asociado con la arquitectura mT5 (para más información sobre las etiquetas de modelo, consulta la <a href="https://huggingface.co/docs/hub/main#how-is-a-models-type-of-inference-api-and-widget-determined" rel="nofollow">documentación de 🤗 Hub</a>). La salida de <code>trainer.push_to_hub()</code> es una URL al hash del commit de Git, ¡así que puedes ver fácilmente los cambios que se realizaron en el repositorio del modelo!</p> <p>Para concluir esta sección, echemos un vistazo a cómo también podemos ajustar mT5 usando las características de bajo nivel proporcionadas por 🤗 Accelerate.</p><!--]--> <!--[0--><!--[1--><h2 class="relative group"><a id="ajuste-fino-de-mt5-con-accelerate" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#ajuste-fino-de-mt5-con-accelerate"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Ajuste fino de mT5 con 🤗 Accelerate</span></h2><!--]--><!----> <p>Ajustar nuestro modelo con 🤗 Accelerate es muy similar al ejemplo de clasificación de texto que encontramos en el <a href="/course/chapter3">Capítulo 3</a>. Las principales diferencias serán la necesidad de generar explícitamente nuestros resúmenes durante el entrenamiento y definir cómo calculamos las puntuaciones ROUGE (recuerda que el <code>Seq2SeqTrainer</code> se encargó de la generación por nosotros). ¡Veamos cómo podemos implementar estos dos requisitos dentro de 🤗 Accelerate!</p> <!--[2--><h3 class="relative group"><a id="preparando-todo-para-el-entrenamiento" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#preparando-todo-para-el-entrenamiento"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Preparando todo para el entrenamiento</span></h3><!--]--><!----> <p>Lo primero que debemos hacer es crear un <code>DataLoader</code> para cada una de nuestras divisiones. Dado que los dataloaders de PyTorch esperan lotes de tensores, necesitamos establecer el formato en <code>"torch"</code> en nuestros datasets:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->tokenized_datasets.set_format(<span class="hljs-string">"torch"</span>)<!----></pre></div><!----> <p>Ahora que tenemos datasets que consisten solo en tensores, lo siguiente que debemos hacer es instanciar el <code>DataCollatorForSeq2Seq</code> nuevamente. Para esto necesitamos proporcionar una versión limpia del modelo, así que carguémoslo nuevamente de nuestro caché:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->model = AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint)<!----></pre></div><!----> <p>Luego podemos instanciar el collator de datos y usarlo para definir nuestros dataloaders:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> torch.utils.data <span class="hljs-keyword">import</span> DataLoader | |
| batch_size = <span class="hljs-number">8</span> | |
| train_dataloader = DataLoader( | |
| tokenized_datasets[<span class="hljs-string">"train"</span>], | |
| shuffle=<span class="hljs-literal">True</span>, | |
| collate_fn=data_collator, | |
| batch_size=batch_size, | |
| ) | |
| eval_dataloader = DataLoader( | |
| tokenized_datasets[<span class="hljs-string">"validation"</span>], collate_fn=data_collator, batch_size=batch_size | |
| )<!----></pre></div><!----> <p>Lo siguiente es definir el optimizador que queremos usar. Al igual que en nuestros otros ejemplos, usaremos <code>AdamW</code>, que funciona bien para la mayoría de los problemas:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> torch.optim <span class="hljs-keyword">import</span> AdamW | |
| optimizer = AdamW(model.parameters(), lr=<span class="hljs-number">2e-5</span>)<!----></pre></div><!----> <p>Finalmente, enviamos nuestro modelo, optimizador y dataloaders al método <code>accelerator.prepare()</code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> accelerate <span class="hljs-keyword">import</span> Accelerator | |
| accelerator = Accelerator() | |
| model, optimizer, train_dataloader, eval_dataloader = accelerator.prepare( | |
| model, optimizer, train_dataloader, eval_dataloader | |
| )<!----></pre></div><!----> <blockquote class="tip"><p>🚨 Si estás entrenando en una TPU, deberás mover todo el código anterior a una función de entrenamiento dedicada. Consulta el <a href="/course/chapter3">Capítulo 3</a> para más detalles.</p></blockquote> <p>Ahora que hemos preparado nuestros objetos, quedan tres cosas por hacer:</p> <ul><li>Definir la programación de la tasa de aprendizaje.</li> <li>Implementar una función para posprocesar los resúmenes para la evaluación.</li> <li>Crear un repositorio en el Hub al que podamos subir nuestro modelo.</li></ul> <p>Para la programación de la tasa de aprendizaje, utilizaremos la programación lineal estándar de las secciones anteriores:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> get_scheduler | |
| num_train_epochs = <span class="hljs-number">10</span> | |
| num_update_steps_per_epoch = <span class="hljs-built_in">len</span>(train_dataloader) | |
| num_training_steps = num_train_epochs * num_update_steps_per_epoch | |
| lr_scheduler = get_scheduler( | |
| <span class="hljs-string">"linear"</span>, | |
| optimizer=optimizer, | |
| num_warmup_steps=<span class="hljs-number">0</span>, | |
| num_training_steps=num_training_steps, | |
| )<!----></pre></div><!----> <p>Para el posprocesamiento, necesitamos una función que divida los resúmenes generados en oraciones separadas por saltos de línea. Este es el formato que espera la métrica ROUGE, y podemos lograrlo con el siguiente fragmento de código:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">def</span> <span class="hljs-title function_">postprocess_text</span>(<span class="hljs-params">preds, labels</span>): | |
| preds = [pred.strip() <span class="hljs-keyword">for</span> pred <span class="hljs-keyword">in</span> preds] | |
| labels = [label.strip() <span class="hljs-keyword">for</span> label <span class="hljs-keyword">in</span> labels] | |
| <span class="hljs-comment"># ROUGE espera un salto de línea después de cada oración</span> | |
| preds = [<span class="hljs-string">"\n"</span>.join(nltk.sent_tokenize(pred)) <span class="hljs-keyword">for</span> pred <span class="hljs-keyword">in</span> preds] | |
| labels = [<span class="hljs-string">"\n"</span>.join(nltk.sent_tokenize(label)) <span class="hljs-keyword">for</span> label <span class="hljs-keyword">in</span> labels] | |
| <span class="hljs-keyword">return</span> preds, labels<!----></pre></div><!----> <p>Esto debería resultarte familiar si recuerdas cómo definimos la función <code>compute_metrics()</code> del <code>Seq2SeqTrainer</code>.</p> <p>Finalmente, necesitamos crear un repositorio de modelos en el Hugging Face Hub. Para esto, podemos usar la biblioteca 🤗 Hub. Solo necesitamos definir un nombre para nuestro repositorio, y la biblioteca tiene una función de utilidad para combinar el ID del repositorio con el perfil de usuario:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> huggingface_hub <span class="hljs-keyword">import</span> get_full_repo_name | |
| model_name = <span class="hljs-string">"test-bert-finetuned-squad-accelerate"</span> | |
| repo_name = get_full_repo_name(model_name) | |
| repo_name<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'lewtun/mt5-finetuned-amazon-en-es-accelerate'</span><!----></pre></div><!----> <p>Ahora podemos usar este nombre de repositorio para clonar una versión local en nuestro directorio de resultados que almacenará los artefactos de entrenamiento:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> huggingface_hub <span class="hljs-keyword">import</span> Repository | |
| output_dir = <span class="hljs-string">"results-mt5-finetuned-squad-accelerate"</span> | |
| repo = Repository(output_dir, clone_from=repo_name)<!----></pre></div><!----> <p>¡Esto nos permitirá subir los artefactos nuevamente al Hub llamando al método <code>repo.push_to_hub()</code> durante el entrenamiento! Concluyamos ahora nuestro análisis escribiendo el bucle de entrenamiento.</p> <!--[2--><h3 class="relative group"><a id="bucle-de-entrenamiento" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#bucle-de-entrenamiento"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Bucle de entrenamiento</span></h3><!--]--><!----> <p>El bucle de entrenamiento para resumen es bastante similar a los otros ejemplos de 🤗 Accelerate que hemos encontrado y se divide aproximadamente en cuatro pasos principales:</p> <ol><li>Entrenar el modelo iterando sobre todos los ejemplos en <code>train_dataloader</code> para cada época.</li> <li>Generar resúmenes del modelo al final de cada época, primero generando los tokens y luego decodificándolos (junto con los resúmenes de referencia) en texto.</li> <li>Calcular las puntuaciones ROUGE utilizando las mismas técnicas que vimos anteriormente.</li> <li>Guardar los puntos de control y subir todo al Hub. Aquí confiamos en el ingenioso argumento <code>blocking=False</code> del objeto <code>Repository</code> para que podamos subir los puntos de control por época de forma <em>asíncrona</em>. ¡Esto nos permite continuar entrenando sin tener que esperar por la subida algo lenta asociada con un modelo del tamaño de un GB!</li></ol> <p>Estos pasos se pueden ver en el siguiente bloque de código:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> tqdm.auto <span class="hljs-keyword">import</span> tqdm | |
| <span class="hljs-keyword">import</span> torch | |
| <span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np | |
| progress_bar = tqdm(<span class="hljs-built_in">range</span>(num_training_steps)) | |
| <span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(num_train_epochs): | |
| <span class="hljs-comment"># Entrenamiento</span> | |
| model.train() | |
| <span class="hljs-keyword">for</span> step, batch <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(train_dataloader): | |
| outputs = model(**batch) | |
| loss = outputs.loss | |
| accelerator.backward(loss) | |
| optimizer.step() | |
| lr_scheduler.step() | |
| optimizer.zero_grad() | |
| progress_bar.update(<span class="hljs-number">1</span>) | |
| <span class="hljs-comment"># Evaluación</span> | |
| model.<span class="hljs-built_in">eval</span>() | |
| <span class="hljs-keyword">for</span> step, batch <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(eval_dataloader): | |
| <span class="hljs-keyword">with</span> torch.no_grad(): | |
| generated_tokens = accelerator.unwrap_model(model).generate( | |
| batch[<span class="hljs-string">"input_ids"</span>], | |
| attention_mask=batch[<span class="hljs-string">"attention_mask"</span>], | |
| ) | |
| generated_tokens = accelerator.pad_across_processes( | |
| generated_tokens, dim=<span class="hljs-number">1</span>, pad_index=tokenizer.pad_token_id | |
| ) | |
| labels = batch[<span class="hljs-string">"labels"</span>] | |
| <span class="hljs-comment"># Si no rellenamos a la longitud máxima, también debemos rellenar las etiquetas</span> | |
| labels = accelerator.pad_across_processes( | |
| batch[<span class="hljs-string">"labels"</span>], dim=<span class="hljs-number">1</span>, pad_index=tokenizer.pad_token_id | |
| ) | |
| generated_tokens = accelerator.gather(generated_tokens).cpu().numpy() | |
| labels = accelerator.gather(labels).cpu().numpy() | |
| <span class="hljs-comment"># Reemplazar -100 en las etiquetas ya que no podemos decodificarlas</span> | |
| labels = np.where(labels != -<span class="hljs-number">100</span>, labels, tokenizer.pad_token_id) | |
| <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(generated_tokens, <span class="hljs-built_in">tuple</span>): | |
| generated_tokens = generated_tokens[<span class="hljs-number">0</span>] | |
| decoded_preds = tokenizer.batch_decode( | |
| generated_tokens, skip_special_tokens=<span class="hljs-literal">True</span> | |
| ) | |
| decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=<span class="hljs-literal">True</span>) | |
| decoded_preds, decoded_labels = postprocess_text( | |
| decoded_preds, decoded_labels | |
| ) | |
| rouge_score.add_batch(predictions=decoded_preds, references=decoded_labels) | |
| <span class="hljs-comment"># Calcular métricas</span> | |
| result = rouge_score.compute() | |
| <span class="hljs-comment"># Extraer las puntuaciones ROUGE medianas</span> | |
| result = {key: value.mid.fmeasure * <span class="hljs-number">100</span> <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> result.items()} | |
| result = {k: <span class="hljs-built_in">round</span>(v, <span class="hljs-number">4</span>) <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> result.items()} | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Epoch <span class="hljs-subst">{epoch}</span>:"</span>, result) | |
| <span class="hljs-comment"># Guardar y subir</span> | |
| accelerator.wait_for_everyone() | |
| unwrapped_model = accelerator.unwrap_model(model) | |
| unwrapped_model.save_pretrained(output_dir, save_function=accelerator.save) | |
| <span class="hljs-keyword">if</span> accelerator.is_main_process: | |
| tokenizer.save_pretrained(output_dir) | |
| repo.push_to_hub( | |
| commit_message=<span class="hljs-string">f"Training in progress epoch <span class="hljs-subst">{epoch}</span>"</span>, blocking=<span class="hljs-literal">False</span> | |
| )<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->Epoch <span class="hljs-number">0</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">5.6351</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">1.1625</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">5.4866</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">5.5005</span>} | |
| Epoch <span class="hljs-number">1</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">9.8646</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">3.4106</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">9.9439</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">9.9306</span>} | |
| Epoch <span class="hljs-number">2</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">11.0872</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">3.3273</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">11.0508</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">10.9468</span>} | |
| Epoch <span class="hljs-number">3</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">11.8587</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">4.8167</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">11.7986</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">11.7518</span>} | |
| Epoch <span class="hljs-number">4</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">12.9842</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">5.5887</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">12.7546</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">12.7029</span>} | |
| Epoch <span class="hljs-number">5</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">13.4628</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">6.4598</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">13.312</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">13.2913</span>} | |
| Epoch <span class="hljs-number">6</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">12.9131</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">5.8914</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">12.6896</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">12.5701</span>} | |
| Epoch <span class="hljs-number">7</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">13.3079</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">6.2994</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">13.1536</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">13.1194</span>} | |
| Epoch <span class="hljs-number">8</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">13.96</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">6.5998</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">13.9123</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">13.7744</span>} | |
| Epoch <span class="hljs-number">9</span>: {<span class="hljs-string">'rouge1'</span>: <span class="hljs-number">14.1192</span>, <span class="hljs-string">'rouge2'</span>: <span class="hljs-number">7.0059</span>, <span class="hljs-string">'rougeL'</span>: <span class="hljs-number">14.1172</span>, <span class="hljs-string">'rougeLsum'</span>: <span class="hljs-number">13.9509</span>}<!----></pre></div><!----> <p>¡Y eso es todo! Una vez que ejecutes esto, tendrás un modelo y resultados bastante similares a los que obtuvimos con el <code>Trainer</code>.</p><!--]--> <!--[1--><h2 class="relative group"><a id="uso-de-tu-modelo-ajustado" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#uso-de-tu-modelo-ajustado"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Uso de tu modelo ajustado</span></h2><!--]--><!----> <p>Una vez que hayas subido el modelo al Hub, puedes probarlo ya sea a través del widget de inferencia o con un objeto <code>pipeline</code>, de la siguiente manera:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline | |
| hub_model_id = <span class="hljs-string">"huggingface-course/mt5-small-finetuned-amazon-en-es"</span> | |
| summarizer = pipeline(<span class="hljs-string">"summarization"</span>, model=hub_model_id)<!----></pre></div><!----> <p>Podemos pasar algunos ejemplos del conjunto de prueba (que el modelo no ha visto) a nuestro pipeline para tener una idea de la calidad de los resúmenes. Primero implementemos una función simple para mostrar la reseña, el título y el resumen generado juntos:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">def</span> <span class="hljs-title function_">print_summary</span>(<span class="hljs-params">idx</span>): | |
| review = books_dataset[<span class="hljs-string">"test"</span>][idx][<span class="hljs-string">"review_body"</span>] | |
| title = books_dataset[<span class="hljs-string">"test"</span>][idx][<span class="hljs-string">"review_title"</span>] | |
| summary = summarizer(books_dataset[<span class="hljs-string">"test"</span>][idx][<span class="hljs-string">"review_body"</span>])[<span class="hljs-number">0</span>][<span class="hljs-string">"summary_text"</span>] | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"'>>> Review: <span class="hljs-subst">{review}</span>'"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"\n'>>> Title: <span class="hljs-subst">{title}</span>'"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"\n'>>> Summary: <span class="hljs-subst">{summary}</span>'"</span>)<!----></pre></div><!----> <p>Echemos un vistazo a uno de los ejemplos en inglés que obtenemos:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->print_summary(<span class="hljs-number">100</span>)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'>>> Review: Nothing special at all about this product... the book is too small and stiff and hard to write in. The huge sticker on the back doesn’t come off and looks super tacky. I would not purchase this again. I could have just bought a journal from the dollar store and it would be basically the same thing. It’s also really expensive for what it is.'</span> | |
| <span class="hljs-string">'>>> Title: Not impressed at all... buy something else'</span> | |
| <span class="hljs-string">'>>> Summary: Nothing special at all about this product'</span><!----></pre></div><!----> <p>¡Esto no está nada mal! Podemos ver que nuestro modelo ha sido capaz de realizar un resumen <em>abstractivo</em> al aumentar partes de la reseña con nuevas palabras. Y quizás el aspecto más interesante de nuestro modelo es que es bilingüe, por lo que también podemos generar resúmenes de reseñas en español:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->print_summary(<span class="hljs-number">0</span>)<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'>>> Review: Es una trilogia que se hace muy facil de leer. Me ha gustado, no me esperaba el final para nada'</span> | |
| <span class="hljs-string">'>>> Title: Buena literatura para adolescentes'</span> | |
| <span class="hljs-string">'>>> Summary: Muy facil de leer'</span><!----></pre></div><!----> <p>El resumen se extrajo en este caso directamente de la reseña. No obstante, esto muestra la versatilidad del modelo mT5 y te ha dado una idea de cómo es trabajar con un corpus multilingüe.</p> <p>A continuación, centraremos nuestra atención en una tarea un poco más compleja: entrenar un modelo de lenguaje desde cero.</p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/course/blob/main/chapters/es/chapter7/5.mdx" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg><!----> <span><span class="underline">Update</span> on GitHub</span></a><!----> <p></p><!--]--><!----><!--]--><!--]--><!--]--> <!--[-1--><!--]--><!--]--> | |
| <script> | |
| { | |
| __sveltekit_agf4mu = { | |
| base: "/docs/course/pr_1352/es", | |
| assets: "/docs/course/pr_1352/es" | |
| }; | |
| const element = document.currentScript.parentElement; | |
| Promise.all([ | |
| import("/docs/course/pr_1352/es/_app/immutable/entry/start.DV9gcfqJ.js"), | |
| import("/docs/course/pr_1352/es/_app/immutable/entry/app.C68Ze5cV.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 44], | |
| data: [null,null], | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 206 kB
- Xet hash:
- 68ae2e648e6eaf7af83570329df3855b0815ecfcfe09acfb5934a9811209aaec
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.