<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Isabel Cristina Nunes de Sousa - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Isabel Cristina Nunes de Sousa - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 19:22:12 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/author/isabel/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Como instalar o TensorFlow e o Keras usando o Anaconda Navigator — sem a linha de comando ]]>
                </title>
                <description>
                    <![CDATA[ Diga não ao pip install na linha de comando! Esta é uma maneira alternativa de instalar TensorFlow em sua máquina local em 3 etapas. Por que estou escrevendo isso? Brinquei com o pip install com múltiplas configurações por várias horas, tentando descobrir como configurar corretamente meu ambiente do Python para ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-instalar-o-tensorflow-e-o-keras-usando-o-anaconda-navigator-sem-a-linha-de-comando/</link>
                <guid isPermaLink="false">65dc9c1dcd7ddc0407292bf2</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jun 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/5f9ca140740569d1a4ca4d8c.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/install-tensorflow-and-keras-using-anaconda-navigator-without-command-line/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to install TensorFlow and Keras using Anaconda Navigator — without the command line</a>
      </p><p>Diga não ao <em>pip install </em>na linha de comando! Esta é uma maneira alternativa de instalar TensorFlow<em> </em>em sua máquina local em 3 etapas.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-239.png" class="kg-image" alt="image-239" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-239.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-239.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-239.png 1080w" sizes="(min-width: 720px) 720px" width="1080" height="810" loading="lazy"></figure><h1 id="por-que-estou-escrevendo-isso">Por que estou escrevendo isso?</h1><p>Brinquei com o <em>pip install</em> com múltiplas configurações por várias horas, tentando descobrir como configurar corretamente meu ambiente do Python para o TensorFlow e o Keras.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-31.png" class="kg-image" alt="image-31" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-31.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-31.png 967w" sizes="(min-width: 720px) 720px" width="967" height="367" loading="lazy"><figcaption>Por que o tensorflow é tão difícil de instalar — mais de 600 mil resultados</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-32.png" class="kg-image" alt="image-32" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-32.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-32.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-32.png 1050w" sizes="(min-width: 720px) 720px" width="1050" height="431" loading="lazy"><figcaption>Não foi possível instalar o tensorflow no windows site:stackoverflow.com — mais de 26 mil resultados</figcaption></figure><h1 id="pouco-antes-de-desistir-descobri-isso-">Pouco antes de desistir, descobri isso…</h1><p><em><a href="https://www.anaconda.com/blog/tensorflow-in-anaconda?source=post_page-">"Um dos principais benefícios da instalação do TensorFlow usando conda em vez de pip é o resultado do sistema de gerenciamento de pacotes do conda. Quando o TensorFlow é instalado usando conda, o conda também instala todas as dependências necessárias e compatíveis para os pacotes."</a></em></p><p>Este artigo orientará você no processo de instalação do TensorFlow e do Keras usando a versão GUI do Anaconda. Presumo que você já tenha baixado e instalado o <a href="https://www.anaconda.com/distribution/?source=post_page---------------------------">Anaconda Navigator</a>.</p><h1 id="vamos-come-ar-">Vamos começar!</h1><ol><li>Inicie o Anaconda Navigator. Vá para a guia Ambientes (<em>Environments</em>) e clique em '<em>Create</em>'.</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-33.png" class="kg-image" alt="image-33" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-33.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-33.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-33.png 1050w" sizes="(min-width: 720px) 720px" width="1050" height="501" loading="lazy"><figcaption>Vá para a guia 'Environments’, clique em ‘Create’</figcaption></figure><p>2. Insira um novo nome de ambiente - (eu coloquei 'tensorflow_env'). <strong>Certifique-se de selecionar <strong>Python 3.6 </strong>aqui<strong>! </strong></strong>Em seguida, clique em 'Create' – o processo pode levar alguns minutos.</p><blockquote>Nota da tradução: o Python, atualmente, está na versão 3.12. O Anaconda também possui novas versões capazes de instalar algo nas versões mais recentes do Python. Caso você queira, pode testar a instalação com versões mais novas.</blockquote><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-34.png" class="kg-image" alt="image-34" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-34.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-34.png 629w" width="629" height="368" loading="lazy"><figcaption>Certifique-se de selecionar Python 3.6</figcaption></figure><p>3. Em seu novo ambiente 'tensorflow_env', selecione 'Not installed' e digite 'tensorflow'. Em seguida, marque 'tensorflow' e clique em 'Apply'. A janela de <em>pop-up</em> aparecerá. Vá em frente e clique em 'Apply'. Esse processo pode levar vários minutos.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-35.png" class="kg-image" alt="image-35" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-35.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-35.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-35.png 1050w" sizes="(min-width: 720px) 720px" width="1050" height="551" loading="lazy"></figure><p>Faça o mesmo para o 'keras'.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-36.png" class="kg-image" alt="image-36" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-36.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-36.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-36.png 1050w" sizes="(min-width: 720px) 720px" width="1050" height="546" loading="lazy"></figure><p>Verifique sua instalação importando os pacotes. Se tudo estiver bem, o comando não retornará nada. Se a instalação não for bem-sucedida, você receberá um erro.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-37.png" class="kg-image" alt="image-37" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-37.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-37.png 780w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Sem pop-up de erro — Sucesso!</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-38.png" class="kg-image" alt="image-38" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-38.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-38.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-38.png 1050w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Você também pode tentar com o Spyder.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-39.png" class="kg-image" alt="image-39" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-39.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/05/image-39.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-39.png 1050w" sizes="(min-width: 720px) 720px" width="1050" height="387" loading="lazy"><figcaption>Sem pop-up de erro — Sucesso!</figcaption></figure><p>Está feito! Você pode seguir <a href="https://towardsdatascience.com/how-to-build-a-neural-network-with-keras-e8faa33d0ae4?source=post_page---------------------------">este artigo</a> (em inglês) para testar seus pacotes recém-instalados. 🙂</p><p>Obrigado pela leitura. Faça os testes!</p><p>Considere seguir o autor no <a href="https://github.com/ekapope?source=post_page---------------------------">GitHub</a>, no <a href="https://medium.com/@ekapope.v?source=post_page---------------------------">Medium</a> e no <a href="https://twitter.com/EkapopeV?source=post_page---------------------------">Twitter</a> para obter mais artigos e tutoriais em seu <em>feed</em>, se gostou do artigo. 🙂</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial de aprendizado de máquina SVM – o que é o algoritmo de máquina de vetores de suporte, explicado com exemplos de códigos ]]>
                </title>
                <description>
                    <![CDATA[ A maioria das tarefas que o aprendizado de máquina realiza atualmente inclui coisas como classificar imagens, traduzir idiomas, lidar com grandes quantidades de dados de sensores e prever valores futuros com base em valores atuais. Você pode escolher diferentes estratégias para se adequar ao problema que está tentando resolver. A ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/tutorial-de-aprendizado-de-maquina-svm/</link>
                <guid isPermaLink="false">656652e113a65603e65022da</guid>
                
                    <category>
                        <![CDATA[ Aprendizagem de máquina ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Sun, 02 Jun 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/SVMs.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/svm-machine-learning-tutorial-what-is-the-support-vector-machine-algorithm-explained-with-code-examples/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">SVM Machine Learning Tutorial – What is the Support Vector Machine Algorithm, Explained with Code Examples</a>
      </p><p>A maioria das tarefas que o aprendizado de máquina realiza atualmente inclui coisas como classificar imagens, traduzir idiomas, lidar com grandes quantidades de dados de sensores e prever valores futuros com base em valores atuais. Você pode escolher diferentes estratégias para se adequar ao problema que está tentando resolver.</p><p>A boa notícia? Existe um algoritmo em aprendizado de máquina que lidará com praticamente todos os dados que você puder lançar nele. Chegaremos lá em um minuto.</p><h2 id="aprendizado-supervisionado-x-n-o-supervisionado"><strong>Aprendizado supervisionado <em>x</em> não supervisionado</strong></h2><p>Duas das estratégias mais comumente usadas em aprendizado de máquina incluem aprendizado supervisionado e aprendizado não supervisionado.</p><h3 id="o-que-o-aprendizado-supervisionado"><strong>O que é o aprendizado supervisionado<strong>?</strong></strong></h3><p>O aprendizado supervisionado ocorre quando você treina um modelo de aprendizado de máquina usando dados rotulados. Isso significa que você tem dados que já possuem a classificação correta associada a eles. Um uso comum do aprendizado supervisionado é ajudá-lo a prever valores para novos dados.</p><p>Com o aprendizado supervisionado, você precisará reconstruir seus modelos à medida que obtém novos dados, para garantir que as previsões retornadas ainda sejam precisas. Um exemplo de aprendizado supervisionado seria rotular imagens de alimentos. Você poderia ter um conjunto de dados dedicado apenas a imagens de pizza para ensinar ao seu modelo o que é uma pizza.</p><h3 id="o-que-o-aprendizado-n-o-supervisionado"><strong>O que é o aprendizado não supervisionado<strong>?</strong></strong></h3><p>O aprendizado não supervisionado ocorre quando você treina um modelo com dados não rotulados. Isso significa que o modelo terá que encontrar suas próprias características e fazer previsões com base em como os dados são classificados. </p><p>Um exemplo de aprendizado não supervisionado seria fornecer ao seu modelo imagens de vários tipos de alimentos sem rótulos. O conjunto de dados teria imagens de pizza, batatas fritas e outros alimentos, e você poderia utilizar algoritmos diferentes para fazer com que o modelo identificasse apenas as imagens de pizza sem nenhum rótulo.</p><h3 id="ent-o-o-que-um-algoritmo"><strong>Então, o que é um algoritmo<strong>?</strong></strong></h3><p>Quando você ouvir pessoas falando sobre algoritmos de aprendizado de máquina, lembre-se de que elas estão falando sobre diferentes equações matemáticas.</p><p>Um algoritmo é apenas uma função matemática personalizável. É por isso que a maioria dos algoritmos possui coisas como funções de custo, valores de peso e parâmetros de funções que você pode alterar com base nos dados com os quais está trabalhando. &nbsp;Basicamente, o aprendizado de máquina é apenas um monte de equações matemáticas que precisam ser resolvidas muito rapidamente.</p><p>É por isso que existem tantos algoritmos diferentes para lidas com diferentes tipos de dados. Um algoritmo em particular é a máquina de vetores de suporte (SVM, do inglês <em>support vector machine</em>) e é isso que este artigo abordará em detalhes.</p><h2 id="o-que-svm"><strong>O que é <strong>SVM?</strong></strong></h2><p>Máquinas de vetores de suporte são um conjunto de métodos de aprendizado supervisionado utilizados para classificação, regressão, e detecção de <em>outliers</em>. Todas essas são tarefas comuns em aprendizado de máquina.</p><p>Você pode utilizá-los para detectar células cancerígenas com base em milhões de imagens ou para prever futuras rotas de direção com um modelo de regressão bem ajustado.</p><p>Existem tipos específicos de SVMs que você pode usar para problemas específicos de aprendizado de máquina, como vetor de suporte de regressão (SVR, do inglês <em>support vector regression</em>), que é uma extensão de vetor de suporte de classificação (SVC, do inglês <em>support vector classification</em>).</p><p>A principal coisa a se ter em mente aqui é que essas são apenas equações matemáticas ajustadas para fornecer a resposta mais precisa o mais rapidamente possível.</p><p>SVMs são diferentes de outros algoritmos de classificação devido à maneira como escolhem a fronteira de decisão (do inglês, <em>decision boundary</em>) que maximiza a distância dos pontos de dados mais próximo de todas as classes. A fronteira de decisão criada pelos SVMs é chamada de classificador de margem máxima ou o hiperplano de margem máxima.</p><h2 id="como-funciona-um-svm"><strong>Como funciona um<strong> SVM</strong></strong></h2><p>Um classificador SVM linear simples funciona criando uma linha reta entre duas classes. Isso significa que todos os pontos de dados de um lado da linha representarão uma categoria, e os pontos de dados do outro lado da linha serão colocados em uma categoria diferente. Isso significa que pode haver um número infinito de linhas para escolher.</p><p>O que torna o algoritmo SVM linear melhor do que alguns dos outros algoritmos, como o k-vizinhos mais próximos, é que ele escolhe a melhor linha para classificar seus pontos de dados. Ele escolhe a linha que separa os dados e que fica o mais distante possível dos pontos de dados mais próximos.</p><p>Um exemplo 2D ajuda a entender todo o jargão do aprendizado de máquina. Basicamente, você tem alguns pontos de dados em uma grade. Você está tentando separar esses pontos de dados pela categoria em que eles deveriam se enquadrar, mas você não quer ter nenhum dado na categoria errada. Isso significa que você está tentando encontrar a linha entre os dois pontos mais próximos que mantém os outros pontos de dados separados.</p><p>Portanto, os dois pontos de dados mais próximos fornecem os vetores de suporte que você usará para encontrar essa reta. Essa linha é chamada de limite de decisão.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/download.png" class="kg-image" alt="download" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/download.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/download.png 640w" width="640" height="480" loading="lazy"><figcaption>SVM linear</figcaption></figure><p>O limite de decisão não precisa ser uma linha. Também é chamado de <em>hiperplano</em>, porque você pode encontrar o limite de decisão com qualquer número de recursos, não apenas dois.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/download--1-.png" class="kg-image" alt="download--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/download--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/download--1-.png 640w" width="640" height="480" loading="lazy"><figcaption>SVM não linear usando kernel RBF</figcaption></figure><h3 id="tipos-de-svms"><strong><strong>T</strong>i<strong>p</strong>o<strong>s</strong> de<strong> SVMs</strong></strong></h3><p>Existem dois tipos diferentes de SVMs, cada um usado para coisas diferentes:</p><ul><li>SVM simples: normalmente usado para regressão linear e problemas de classificação.</li><li>SVM kernel: tem mais flexibilidade para dados não lineares porque você pode adicionar mais recursos para ajustar um hiperplano em vez de um espaço bidimensional.</li></ul><h2 id="por-que-svms-s-o-usados-em-aprendizado-de-m-quina">Por que SVMs são usados em aprendizado de máquina?</h2><p>SVMs são usados em aplicações como reconhecimento de escrita, detecção de intrusão, reconhecimento facial, classificação de e-mail, classificação de genes, e em páginas da<em> web</em>. Essa é uma das razões pelas quais usamos SVMs no aprendizado de máquina. Ele pode lidar tanto com classificação quanto regressão em dados lineares e não lineares.</p><p>Outra razão pela qual usamos SVMs é o fato de que eles podem encontrar relações complexas entre seus dados sem que você precise fazer muitas transformações por conta própria. É uma ótima opção quando você trabalha com conjuntos de dados menores, que possuem dezenas a centenas de milhares de recursos. Eles normalmente encontram resultados mais precisos quando comparados a outros algoritmos devido à sua capacidade de lidar com conjuntos de dados pequenos e complexos.</p><p>Aqui estão alguns dos prós e contras do uso de SVMs.</p><h3 id="pr-s"><strong><strong>P</strong>ró<strong>s</strong></strong></h3><ul><li>Eficaz em conjuntos de dados com múltiplas características, como dados financeiros ou médicos.</li><li>Eficaz nos casos em que o número de recursos é maior que o número de pontos de dados.</li><li>Usa um subconjunto de pontos de treinamento na função de decisão chamados vetores de suporte, o que o torna eficiente em termos de memória.</li><li>Diferentes funções de kernel podem ser especificadas para a função de decisão. Você pode usar kernels comuns, mas também é possível especificar kernels personalizados.</li></ul><h3 id="contras"><strong><strong>Con</strong>tra<strong>s</strong></strong></h3><ul><li>Se o número de características for muito maior que o número de pontos de dados, é crucial evitar o sobreajuste (em inglês, <em>overfitting</em>) ao escolher as funções do kernel e o termo de regularização.</li><li>SVMs não fornecem estimativas de probabilidade diretamente. Elas são calculados usando uma cara validação cruzada quíntupla.</li><li>Funciona melhor em pequenos conjuntos de amostras devido ao seu alto tempo de treinamento.</li></ul><p>Como os SVMs podem usar qualquer número de kernels, é importante que você conheça alguns deles.</p><h2 id="fun-es-do-kernel"><strong>Funções do k<strong>ernel</strong></strong></h2><h3 id="linear"><strong><strong>Linear</strong></strong></h3><p>Eles são comumente recomendados para classificação de texto, pois a maioria desses tipos de problemas de classificação são linearmente separáveis.</p><p>O kernel linear funciona muito bem quando há muitas características, e os problemas de classificação de texto têm muitas características. As funções lineares do kernel são mais rápidas que a maioria das outras e você tem menos parâmetros para otimizar.</p><p>Aqui está a função que define o kernel linear:</p><pre><code>f(X) = w^T * X + b</code></pre><p>Nesta equação, <strong>w</strong> é o vetor de peso (do inglês, <em>weight</em>) que você deseja minimizar, <strong>X</strong> são os dados que você está tentando classificar e <strong>b</strong> é o coeficiente linear estimado a partir dos dados de treinamento. Esta equação define o limite de decisão que o SVM retorna.</p><h3 id="polinomial"><strong><strong>Pol</strong>i<strong>nomial</strong></strong></h3><p>O kernel polinomial não é usado na prática com muita frequência porque não é tão eficiente computacionalmente quanto outros kernels e suas previsões não são tão precisas.</p><p>Aqui está a função para um kernel polinomial:</p><pre><code>f(X1, X2) = (a + X1^T * X2) ^ b</code></pre><p>Essa é uma das equações polinomiais de kernel mais simples que você pode usar. <strong>f(X1, X2)</strong> representa o limite de decisão polinomial que separará seus dados. <strong>X1</strong> e <strong>X2</strong> representam seus dados.</p><h3 id="fun-o-de-base-radial-gaussiana-rbf-">Função de base radial gaussiana<strong><strong> (RBF)</strong></strong></h3><p>Esse é um dos kernels mais poderosos e comumente usados em SVMs. Ele geralmente é a escolha para dados não lineares.</p><p>Aqui está a equação para um kernel RBF:</p><pre><code>f(X1, X2) = exp(-gamma * ||X1 - X2||^2)</code></pre><p>Nesta equação, <strong>gama</strong> especifica quanto um único ponto de treinamento tem sobre os outros pontos de dados ao seu redor. ||<strong>X1 - X2</strong>|| é o produto escalar entre seus recursos.</p><h3 id="sigmoide"><strong><strong>Sigmoid</strong>e</strong></h3><p>Mais útil em redes neurais do que em máquinas de vetores de suporte, mas há casos de uso específicos ocasionais.</p><p>Aqui está a função para um kernel sigmoide:</p><pre><code>f(X, y) = tanh(alpha * X^T * y + C)</code></pre><p>Nesta função, <strong>alfa</strong> é um vetor de peso e <strong>C</strong> é um valor de deslocamento para explicar alguns erros de classificação de dados que podem ocorrer.</p><h3 id="outros"><strong><strong>O</strong>u<strong>tr</strong>o<strong>s</strong></strong></h3><p>Existem muitos outros kernels que você pode usar em seu projeto. Essa pode ser uma decisão a ser tomada quando você precisar atender a certas restrições de erro, quiser tentar acelerar o tempo de treinamento ou quiser superajustar os parâmetros.</p><p><a href="https://data-flair.training/blogs/svm-kernel-functions/">Alguns outros kernels incluem</a>: ANOVA de base radial, tangente hiperbólica e Laplace RBF (texto em inglês).</p><p>Agora que você sabe um pouco sobre como os kernels funcionam nos bastidores, vamos ver alguns exemplos.</p><h2 id="exemplos-com-conjuntos-de-dados"><strong><strong>Ex</strong>e<strong>mpl</strong>o<strong>s </strong>com conjuntos de dados</strong></h2><p>Para mostrar como os SVMs funcionam na prática, passaremos pelo processo de treinamento de um modelo com ele usando a biblioteca <a href="https://scikit-learn.org/stable/">Python Scikit-learn</a>. Essa biblioteca é comumente usada em todos os tipos de problemas de aprendizado de máquina e funciona bem com outras bibliotecas Python.</p><p>Aqui estão as etapas encontradas regularmente em projetos de aprendizado de máquina:</p><ul><li>Importe o conjunto de dados</li><li>Explore os dados para descobrir como eles são</li><li>Pré-processe os dados</li><li>Divida os dados em atributos e rótulos</li><li>Divida os dados em conjuntos de treinamento e teste</li><li>Treine o algoritmo SVM</li><li>Faça algumas previsões</li><li>Avalie os resultados do algoritmo</li></ul><p>Algumas dessas etapas podem ser combinadas dependendo de como você lida com seus dados. Faremos um exemplo com um SVM linear e um SVM não linear. Você pode encontrar o <a href="https://github.com/flippedcoder/probable-waddle/blob/master/svm_point_ex.py">código para esses exemplos aqui</a>.</p><h3 id="exemplo-de-svm-linear"><strong>Exemplo de SVM l<strong>inear</strong></strong></h3><p>Começaremos importando algumas bibliotecas que facilitarão o trabalho com a maioria dos projetos de aprendizado de máquina.</p><pre><code class="language-python">import matplotlib.pyplot as plt
import numpy as np
from sklearn import svm</code></pre><p>Para um exemplo linear simples, faremos apenas alguns dados fictícios e que atuarão no lugar da importação de um conjunto de dados.</p><pre><code class="language-python"># dados lineares
X = np.array([1, 5, 1.5, 8, 1, 9, 7, 8.7, 2.3, 5.5, 7.7, 6.1])
y = np.array([2, 8, 1.8, 8, 0.6, 11, 10, 9.4, 4, 3, 8.8, 7.5])</code></pre><p>A razão pela qual estamos trabalhando com arrays numpy é para tornar as operações de matriz mais rápidas, pois elas usam menos memória do que as listas do Python. Você também pode aproveitar a digitação do conteúdo dos arrays. Agora, vamos dar uma olhada na aparência dos dados em um gráfico:</p><pre><code class="language-python"># exibir dados não classificados
plt.scatter(X, y)
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/linear-svm_raw.png" class="kg-image" alt="linear-svm_raw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/linear-svm_raw.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/linear-svm_raw.png 640w" width="640" height="480" loading="lazy"></figure><p>Depois de ver a aparência dos dados, você poderá adivinhar melhor qual algoritmo funcionará melhor para você. Tenha em mente que esse é um conjunto de dados muito simples. Então, na maioria das vezes, você precisará trabalhar em seus dados para colocá-los em um estado utilizável.</p><p>Faremos um pré-processamento no código já estruturado. Isso colocará os dados brutos em um formato que podemos usar para treinar o modelo SVM.</p><pre><code class="language-python"># modelando os dados para o treinamento do modelo
training_X = np.vstack((X, y)).T
training_y = [0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1]</code></pre><p>Agora, podemos criar o modelo SVM usando um kernel linear.</p><pre><code class="language-python"># defina o modelo
clf = svm.SVC(kernel='linear', C=1.0)</code></pre><p>Essa linha de código acabou de criar um modelo completo de aprendizado de máquina. Agora, só precisamos treiná-lo com os dados que pré-processamos.</p><pre><code class="language-python"># treine o model
clf.fit(training_X, training_y)</code></pre><p>É assim que você pode construir um modelo para qualquer projeto de aprendizado de máquina. O conjunto de dados que temos pode ser pequeno, mas se você encontrar um conjunto de dados do mundo real que possa ser classificado com um limite linear, esse modelo ainda funcionará.</p><p>Com seu modelo treinado, você pode fazer previsões sobre como um novo ponto de dados será classificado e criar um gráfico do limite de decisão. Vamos traçar o limite de decisão.</p><pre><code class="language-python"># obter os valores ponderados para a equação lineara partir do modelo do SVM treinado
w = clf.coef_[0]

# obter o deslocamento de y para a equação linear
a = -w[0] / w[1]

# criar o espaço do eixo x para os pontos de dados
XX = np.linspace(0, 13)

# obter os valores de y para colocar a fronteira de decisão no gráfico
yy = a * XX - clf.intercept_[0] / w[1]

# colocar a fronteira de decisão no gráfico
plt.plot(XX, yy, 'k-')

# exibir o gráfico visualmente
plt.scatter(training_X[:, 0], training_X[:, 1], c=training_y)
plt.legend()
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/linear-svm.png" class="kg-image" alt="linear-svm" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/linear-svm.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/linear-svm.png 640w" width="640" height="480" loading="lazy"></figure><h3 id="exemplo-de-svm-n-o-linear"><strong>Exemplo de <strong>SVM </strong>não linear</strong></h3><p>Neste exemplo, usaremos um conjunto de dados um pouco mais complicado para mostrar uma das áreas em que os SVMs se destacam. Vamos importar alguns pacotes.</p><pre><code class="language-python">import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
from sklearn import svm</code></pre><p>Esse conjunto de importações é semelhante ao do exemplo linear, exceto que importa mais uma coisa. Agora, podemos usar um conjunto de dados diretamente da biblioteca Scikit-learn.</p><pre><code class="language-python"># dados não lineares
circle_X, circle_y = datasets.make_circles(n_samples=300, noise=0.05)</code></pre><p>A próxima etapa é dar uma olhada na aparência desses dados brutos em um gráfico.</p><pre><code class="language-python"># mostrar os dados não lineares brutos (raw)
plt.scatter(circle_X[:, 0], circle_X[:, 1], c=circle_y, marker='.')
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/nonlinear-svm_raw.png" class="kg-image" alt="nonlinear-svm_raw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/nonlinear-svm_raw.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/nonlinear-svm_raw.png 640w" width="640" height="480" loading="lazy"></figure><p>Agora que você pode ver como os dados são separados, podemos escolher um SVM não linear para começar. Esse conjunto de dados não precisa de nenhum pré-processamento antes de usá-lo para treinar o modelo. Portanto, podemos pular essa etapa. Aqui vemos como o modelo SVM ficará para isso:</p><pre><code class="language-python"># criar o algoritmo não linear para o modelo
nonlinear_clf = svm.SVC(kernel='rbf', C=1.0)</code></pre><p>Nesse caso, usaremos um <a href="http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=MachineLearning&amp;doc=exercises/ex8/ex8.html">kernel RBF (Função de Base Radial Gaussiana)</a> para classificar esses dados. Você também pode tentar o kernel polinomial para ver a diferença entre os resultados obtidos. Agora, é hora de treinar o modelo.</p><pre><code class="language-python"># treinamento do modelo não linear
nonlinear_clf.fit(circle_X, circle_y)</code></pre><p>Você pode começar a rotular novos dados na categoria correta com base nesse modelo. Para ver como é o limite de decisão, teremos que criar uma função personalizada para representá-lo.</p><pre><code class="language-python"># Crie o gráfico para a fronteira de decisão para um problema do SVM não linear
def plot_decision_boundary(model, ax=None):
    if ax is None:
        ax = plt.gca()
        
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    
    # crie a grade para avaliar o modelo
    x = np.linspace(xlim[0], xlim[1], 30)
    y = np.linspace(ylim[0], ylim[1], 30)
    Y, X = np.meshgrid(y, x)

	# modele os dados
    xy = np.vstack([X.ravel(), Y.ravel()]).T
    
	# obtenha a fronteira de decisão com base no modelo
    P = model.decision_function(xy).reshape(X.shape)
    
    # crie o gráfico para a fronteira de decisão
    ax.contour(X, Y, P,
               levels=[0], alpha=0.5,
               linestyles=['-'])</code></pre><p>Você tem tudo o que precisa para traçar o limite de decisão para esses dados não lineares. Podemos fazer isso com algumas linhas de código que usam a <a href="https://matplotlib.org/">biblioteca Matlibplot</a>, assim como os outros gráficos.</p><pre><code class="language-python"># crie o gráfico para os dados e para a fronteira de decisão
plt.scatter(circle_X[:, 0], circle_X[:, 1], c=circle_y, s=50)
plot_decision_boundary(nonlinear_clf)
plt.scatter(nonlinear_clf.support_vectors_[:, 0], nonlinear_clf.support_vectors_[:, 1], s=50, lw=1, facecolors='none')
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/nonlinear-svm.png" class="kg-image" alt="nonlinear-svm" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/nonlinear-svm.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/nonlinear-svm.png 640w" width="640" height="480" loading="lazy"></figure><p>Quando você tem seus dados e conhece o problema que está tentando resolver, tudo pode ser realmente simples assim.</p><p>Você pode alterar completamente seu modelo de treinamento, escolher diferentes algoritmos e recursos para trabalhar e ajustar seus resultados com base em vários parâmetros. Existem bibliotecas e pacotes para tudo isso agora, então não há muita matemática com a qual você precise lidar.</p><h2 id="dicas-para-problemas-do-mundo-real"><strong>Dicas para <strong>problem</strong>a<strong>s</strong> do mundo real</strong></h2><p>Os conjuntos de dados do mundo real têm alguns problemas comuns devido ao tamanho que podem ter, aos diversos tipos de dados que contêm e a quanto poder de computação podem precisar para treinar um modelo.</p><p>Existem algumas coisas que você deve observar com SVMs em particular:</p><ul><li>Certifique-se de que seus dados estejam em formato numérico em vez de categórico. Os SVMs esperam números em vez de outros tipos de rótulos.</li><li>Evite copiar dados tanto quanto possível. Algumas bibliotecas do Python duplicarão seus dados se eles não estiverem em um formato específico. A cópia de dados também diminuirá o tempo de treinamento e distorcerá a maneira como o modelo atribui os pesos a um recurso específico.</li><li>Observe o tamanho do cache do kernel, pois ele usa sua RAM. Se você tiver um conjunto de dados muito grande, isso poderá causar problemas ao seu sistema.</li><li>Dimensione seus dados, pois os algoritmos SVM não são invariantes à escala. Isso significa que você pode converter todos os seus dados para ficarem dentro dos intervalos de [0, 1] ou [-1, 1].</li></ul><h2 id="outras-considera-es"><strong><strong>O</strong>utras considerações</strong></h2><p>Você pode se perguntar por que não entrei em detalhes profundos da matemática aqui. Isso ocorreu, principalmente, pelo fato de que eu não quero assustar as pessoas e impedi-las de aprender mais sobre aprendizado de máquina.</p><p>É divertido aprender sobre essas equações matemáticas longas e complicadas e suas derivações, mas é raro você escrever seus próprios algoritmos e provas em projetos reais.</p><p>É como ocorre com a maioria das outras coisas que você usa todos os dias, como o telefone ou o computador. Você pode fazer tudo o que precisa sem saber como os processadores são construídos.</p><p>O aprendizado de máquina é como qualquer outra aplicação da engenharia de <em>software</em>. Existem vários pacotes que tornam mais fácil obter os resultados necessários sem um conhecimento profundo em estatística.</p><p>Depois de praticar um pouco com os diferentes pacotes e bibliotecas disponíveis, você descobrirá que a parte mais difícil do aprendizado de máquina é obter e rotular seus dados.</p><p>A autora trabalha em neurociência, aprendizado de máquina e com questões baseadas na <em>web</em>! Siga a autora no <a href="https://twitter.com/flippedcoding">Twitter</a> para saber mais a respeito e sobre outras coisas interessantes em tecnologia.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como embutir visualizações interativas em seu site com Python e Matplotlib ]]>
                </title>
                <description>
                    <![CDATA[ Em um tutorial anterior do freeCodeCamp, expliquei como criar visualizações de dados com atualizações automáticas em Python [https://www.freecodecamp.org/news/how-to-create-auto-updating-data-visualizations-in-python-with-matplotlib-and-aws/]  (texto em inglês). Alguns leitores perguntaram se havia algum modo de tornar as visualizações interativas. Felizmente, uma solução fácil já está disponível! Neste tutorial, vou ensinar como você pode criar visualizações ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-embutir-visualizacoes-interativas-em-seu-site-com-python-e-matplotlib/</link>
                <guid isPermaLink="false">650995fcade67a03f81e5383</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Thu, 04 Apr 2024 12:27:42 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/03/bank_data.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-embed-interactive-python-visualizations-on-your-website-with-python-and-matplotlib/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Embed Interactive Python Visualizations on Your Website with Python and Matplotlib</a>
      </p><p>Em um tutorial anterior do freeCodeCamp, expliquei <a href="https://www.freecodecamp.org/news/how-to-create-auto-updating-data-visualizations-in-python-with-matplotlib-and-aws/">como criar visualizações de dados com atualizações automáticas em Python</a> (texto em inglês).</p><p>Alguns leitores perguntaram se havia algum modo de tornar as visualizações interativas. Felizmente, uma solução fácil já está disponível!</p><p>Neste tutorial, vou ensinar como você pode criar visualizações interativas de dados em Python. Essas visualizações são excelentes candidatas para incorporação em seu blog ou site.</p><h2 id="a-visualiza-o-de-dados-espec-fica-com-a-qual-trabalharemos"><strong>A visualização de dados específica com a qual trabalharemos</strong></h2><p>Em vez de construir uma visualização de dados inteira do zero neste artigo, trabalharemos com a visualização que criamos em meu último tutorial.</p><p>A visualização usa <a href="https://nickmccullum.com/advanced-python/pandas-dataframes/">pandas</a>, <a href="https://nickmccullum.com/python-visualization/how-to-import-matplotlib/">matplotlib</a> e <a href="https://nickmccullum.com/advanced-python/">Python</a> para apresentar vários pontos de dados dos 5 maiores bancos de capital aberto dos Estados Unidos.</p><p>Aqui está uma imagem estática da visualização que criamos:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/03/image-55.png" class="kg-image" alt="image-55" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/03/image-55.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/03/image-55.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/03/image-55.png 1246w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>O código real para a visualização está incluído abaixo. Abordamos isso no último tutorial, mas observe que você precisará gerar sua própria chave de API IEX Cloud e incluí-la na variável <code>IEX_API_Key</code> para que o script funcione.</p><pre><code class="language-python">############################
#Importação das dependências
############################

import pandas as pd
import matplotlib.pyplot as plt

###############################
#Importação e limpeza dos dados
###############################

IEX_API_Key = ''

tickers = [
            'JPM',
            'BAC',
            'C',
            'WFC',
            'GS',
            ]

#Crie uma string vazia chamada `ticker_string`, a qual adicionaremos tickers e vírgulas
ticker_string = ''

#Percorra cada elemento de `tickers` e adicione-os com uma vírgula a ticker_string
for ticker in tickers:
    ticker_string += ticker
    ticker_string += ','
    
#Remova a última vírgula de `ticker_string`
ticker_string = ticker_string[:-1]

#Crie as strings endpoint e years
endpoints = 'chart'
years = '5'

#Faça a interpolação das strings endpoint em HTTP_request string
HTTP_request = f'https://cloud.iexapis.com/stable/stock/market/batch?symbols={ticker_string}&amp;types={endpoints}&amp;range={years}y&amp;cache=true&amp;token={IEX_API_Key}'

#Envie a solicitação HTTP à API IEX Cloud e armazene a resposta em um DataFrame do pandas
bank_data = pd.read_json(HTTP_request)

#Crie uma lista vazia, onde adicionaremos uma série do pandas de dados de preços de ações
series_list = []

#Percorra cada um dos tickers e mostre uma série do pandas com seus preços ao encerramento da bolsa nos últimos 5 anos
for ticker in tickers:
    series_list.append(pd.DataFrame(bank_data[ticker]['chart'])['close'])

#Adicione a coluna dates (datas)
series_list.append(pd.DataFrame(bank_data['JPM']['chart'])['date'])

#Copie a lista 'tickers' que aparece anteriormente no script e adicione um novo elemento chamado 'Date'. 
#Esses elementos serão os nomes das colunas de nosso DataFrame do pandas posteriormente.
column_names = tickers.copy()
column_names.append('Date')

#Concatene as séries do pandas Series em um único DataFrame
bank_data = pd.concat(series_list, axis=1)

#Nomeie as colunas do DataFrame e defina a coluna 'Date' como o índice
bank_data.columns = column_names
bank_data.set_index('Date', inplace = True)

########################
#Crie a imagem do Python
########################

#Defina o tamanho do canvas do matplotlib
fig = plt.figure(figsize = (18,8))

################################################
################################################
#Crie subgráficos no Python
################################################
################################################

########################
#Subgráfico 1
########################
plt.subplot(2,2,1)

#Gere o diagrama de caixas (boxplot)
plt.boxplot(bank_data.transpose())

#Adicione títulos ao gráfico e aos eixos
plt.title('Boxplot of Bank Stock Prices (5Y Lookback)')
plt.xlabel('Bank')
plt.ylabel('Stock Prices')

#Adicione os rótulos a cada diagrama de caixas individual no canvas
ticks = range(1, len(bank_data.columns)+1)
labels = list(bank_data.columns)
plt.xticks(ticks,labels)

########################
#Subgráfico 2
########################
plt.subplot(2,2,2)

#Crie os dados do eixo x
dates = bank_data.index.to_series()
dates = [pd.to_datetime(d) for d in dates]

#Crie os dados do eixo y
WFC_stock_prices =  bank_data['WFC']

#Gere o gráfico de dispersão (scatterplot)
plt.scatter(dates, WFC_stock_prices)

#Adicione títulos ao gráfico e aos eixos
plt.title("Wells Fargo Stock Price (5Y Lookback)")
plt.ylabel("Stock Price")
plt.xlabel("Date")

########################
#Subgráfico 3
########################
plt.subplot(2,2,3)

#Crie os dados do eixo x
dates = bank_data.index.to_series()
dates = [pd.to_datetime(d) for d in dates]

#Crie os dados do eixo y
BAC_stock_prices =  bank_data['BAC']

#Gere o gráfico de dispersão (scatterplot)
plt.scatter(dates, BAC_stock_prices)

#Adicione títulos ao gráfico e aos eixos
plt.title("Bank of America Stock Price (5Y Lookback)")
plt.ylabel("Stock Price")
plt.xlabel("Date")

########################
#Subgráfico 4
########################
plt.subplot(2,2,4)

#Gere o histograma
plt.hist(bank_data.transpose(), bins = 50)

#Adicione uma legenda ao histograma
plt.legend(bank_data.columns,fontsize=10)

#Adicione títulos ao gráfico e aos eixos
plt.title("A Histogram of Daily Closing Stock Prices for the 5 Largest Banks in the US (5Y Lookback)")
plt.ylabel("Observations")
plt.xlabel("Stock Prices")

plt.tight_layout()

################################################
#Salve a imagem em sua máquina local
################################################

plt.savefig('bank_data.png')</code></pre><p>Agora que entendemos a visualização específica com a qual trabalharemos, vamos falar sobre o que significa uma visualização ser interativa.</p><h2 id="o-que-significa-uma-visualiza-o-ser-interativa"><strong>O que significa uma visualização ser interativa<strong>?</strong></strong></h2><p>Existem dois tipos de visualizações de dados que são úteis para embutir em seu site.</p><p>O primeiro tipo é uma visualização estática. Esta é basicamente uma imagem - pense em arquivos <code>.png</code> ou <code>.jpg</code>.</p><p>O segundo tipo é uma visualização dinâmica. Essas visualizações mudam em resposta ao comportamento do usuário, geralmente via panorâmica ou zoom. As visualizações dinâmicas não são armazenadas em arquivos <code>.png</code> ou <code>.jpg</code>, mas geralmente em tags <code>svg</code> ou <code>iframe</code>.</p><p>Este tutorial é sobre criação de visualizações dinâmicas de dados. Especificamente, a visualização que queremos criar terá as seguintes características:</p><ol><li>Você clicará em um botão no canto inferior esquerdo para ativar o modo dinâmico.</li><li>Depois que o modo dinâmico estiver ativado, você poderá ampliar e deslocar a visualização com o mouse.</li><li>Você também pode cortar e dar zoom em uma seção específica da visualização.</li></ol><p>Na próxima seção deste tutorial, você aprenderá como instalar e importar a biblioteca <code>mpld3</code>, que é a dependência do Python que usaremos para criar nossos gráficos interativos.</p><h2 id="como-importar-a-biblioteca-mpld3"><strong>Como importar a biblioteca<strong> mpld3</strong></strong></h2><p>Para usar a biblioteca <code>mpld3</code> em nossa aplicação do Python, há duas etapas que precisamos concluir primeiro:</p><ol><li>Instalar a biblioteca <code>mpld3</code> na máquina em que estamos trabalhando.</li><li>Importar a biblioteca <code>mpld3</code> em nosso script do Python.</li></ol><p>Primeiro, vamos instalar o <code>mpld3</code> em nossa máquina local.</p><p>A maneira mais fácil de fazer isso é usando o gerenciador de pacotes <code>pip</code> para Python3. Se você já tem o <code>pip</code> instalado em sua máquina, você pode fazer isso executando a seguinte declaração na sua linha de comando:</p><pre><code class="language-bash">pip3 install mpld3</code></pre><p>Agora que o <code>mpld3</code> está instalado em sua máquina, podemos importá-lo para nosso script do Python com a seguinte declaração:</p><pre><code class="language-python">import mpld3</code></pre><p>Para facilitar a leitura, é considerada uma prática recomendada incluir essa importação junto com o restante das importações na parte superior de seu script. Isso significa que agora sua seção de importação ficará assim:</p><pre><code class="language-python">############################
#Importação das dependências
############################

import pandas as pd
import matplotlib.pyplot as plt
import mpld3</code></pre><h2 id="como-transformar-uma-visualiza-o-est-tica-do-matplotlib-em-uma-visualiza-o-interativa-de-dados"><strong>Como transformar uma visualização estática do <strong><code>matplotlib</code> </strong>em uma visualização interativa de dados</strong></h2><p>A principal funcionalidade da biblioteca <code>mpld3</code> é pegar uma visualização <code>matplotlib</code> existente e transformá-la em algum código HTML que você pode embutir em seu site.</p><p>A ferramenta que usamos para isso é o arquivo <code>fig_to_html</code> do <code>mpld3</code>, que aceita um objeto <code>figure</code> do <code>matplotlib</code> como seu único argumento e retorna HTML.</p><p>Para usar o método <code>fig_to_html</code> para nosso propósito, basta adicionar o seguinte código ao final do nosso script do Python:</p><pre><code class="language-python">html_str = mpld3.fig_to_html(fig)
Html_file= open("index.html","w")
Html_file.write(html_str)
Html_file.close()</code></pre><p>Este código gera o HTML e o salva com o nome de arquivo <code>index.html</code> em seu diretório de trabalho atual. Esta é a aparência disso quando renderizado em uma página da web:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/03/Screenshot-from-2024-03-24-14-28-48.png" class="kg-image" alt="Screenshot-from-2024-03-24-14-28-48" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/03/Screenshot-from-2024-03-24-14-28-48.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/03/Screenshot-from-2024-03-24-14-28-48.png 962w" width="600" height="400" loading="lazy"></figure><p>Ao passar o mouse sobre esta visualização, três ícones aparecerão no canto inferior esquerdo. O ícone esquerdo retorna a visualização à sua aparência padrão. O ícone do meio ativa o modo dinâmico. O ícone direito permite cortar e aplicar zoom em um ponto específico da visualização.</p><h2 id="um-erro-comum-ao-trabalhar-com-pandas-e-mpld3"><strong>Um erro comum ao trabalhar com<strong> pandas </strong>e<strong> mpld3</strong></strong></h2><p>Ao criar a visualização interativa neste tutorial, você pode encontrar o seguinte erro gerado pelo <code>mpld3</code>:</p><pre><code>TypeError: array([ 1.]) is not JSON serializable</code></pre><p>Felizmente, existe uma solução bem documentada para esse erro no <a href="https://github.com/mpld3/mpld3/issues/441">GitHub</a>.</p><p>Você precisa editar o arquivo _display.py encontrado em Lib\site-packages\mpld3 e substituir a classe NumpyEncoder por esta:</p><pre><code>class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy types """

    def default(self, obj):
        if isinstance(obj, (numpy.int_, numpy.intc, numpy.intp, numpy.int8,
            numpy.int16, numpy.int32, numpy.int64, numpy.uint8,
            numpy.uint16,numpy.uint32, numpy.uint64)):
            return int(obj)
        elif isinstance(obj, (numpy.float_, numpy.float16, numpy.float32, 
            numpy.float64)):
            return float(obj)
        try: # Added by ceprio 2018-04-25
            iterable = iter(obj)
        except TypeError:
            pass
        else:
            return list(iterable)
         # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, obj)</code></pre><p>Depois que essa substituição for feita, seu código deverá funcionar corretamente e seu arquivo <code>index.html</code> deverá ser gerado com êxito.</p><h2 id="reflex-es-finais"><strong>Reflexões finais</strong></h2><p>Neste tutorial, você aprendeu como criar visualizações interativas de dados em Python usando as bibliotecas matplotlib e mpld3. Aqui está um resumo específico do que abordamos:</p><ol><li>A definição de uma visualização dinâmica de dados</li><li>Como instalar e importar a biblioteca <code>mpld3</code> em Python</li><li>Como usar a biblioteca <code>mpld3</code> para transformar uma visualização do <code>matplotlib</code> em uma visualização dinâmica que você pode embutir em seu site</li><li>Como corrigir um erro comum que os usuários da biblioteca <code>mpld3</code> enfrentam</li></ol><p>Este tutorial foi escrito por <a href="https://nickmccullum.com/">Nick McCullum</a>, que ensina desenvolvimento em <a href="https://nickmccullum.com/advanced-python/">Python</a> e <a href="https://nickmccullum.com/javascript/">JavaScript</a> em seu site.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Se você tiver loops lentos em Python, você pode consertá-los…até não poder mais ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Maxim Mamaev Vamos pegar um problema computacional como exemplo, escrever o código e ver como podemos melhorar o tempo de execução. Aqui vamos nós. Montando a cena: o problema da mochila Este é o problema computacional que usaremos como exemplo: O problema da mochila [https://pt.wikipedia.org/wiki/Problema_da_mochila] é um problema ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/se-voce-tiver-loops-lentos-em-python-pode-tentar-conserta-los/</link>
                <guid isPermaLink="false">64b01e8eb04bf0067ce23b23</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Wed, 13 Sep 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_t5vZrkc3PdQZ78RX7Jx8Lg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/if-you-have-slow-loops-in-python-you-can-fix-it-until-you-cant-3a39e03b6f35/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">If you have slow loops in Python, you can fix it…until you can’t</a>
      </p><p>Escrito por: Maxim Mamaev</p><p>Vamos pegar um problema computacional como exemplo, escrever o código e ver como podemos melhorar o tempo de execução. Aqui vamos nós.</p><h3 id="montando-a-cena-o-problema-da-mochila">Montando a cena: o problema da mochila</h3><p>Este é o problema computacional que usaremos como exemplo:</p><p>O <a href="https://pt.wikipedia.org/wiki/Problema_da_mochila">problema da mochila</a> é um problema bem conhecido em otimização combinatória. Nesta seção, revisaremos seu tipo mais comum, o <strong>problema da mochila <strong>0–1</strong></strong>, e sua solução por meio de programação dinâmica. Se você estiver familiarizado com o assunto, pode pular essa parte.</p><p>Você recebe uma mochila de capacidade <strong><strong>C<em><em> </em></em></strong></strong>e uma coleção de <strong><strong>N</strong></strong> itens. Cada item tem peso <strong><strong>w[i]</strong></strong> e valor <strong><strong>v[i]</strong></strong>. Sua tarefa é arrumar a mochila com os itens mais valiosos. Em outras palavras, você deve maximizar o valor total dos itens que coloca na mochila, com uma restrição: o peso total dos itens levados <strong>não pode</strong> exceder a capacidade da mochila.</p><p>Depois de obter uma solução, o peso total dos itens na mochila é chamado de "peso da solução" e seu valor total é o "valor da solução".</p><p>O problema tem muitas aplicações práticas. Por exemplo, você decidiu investir R$ 1.600 em uma famosa ação da FAANG (nome coletivo das ações do Facebook, Amazon, Apple, Netflix e Google, também conhecida como Alphabet). Cada ação tem um preço de mercado atual e a estimativa de preço de um ano. A partir de um dia em 2018, eles são os seguintes:</p><pre><code>========= ======= ======= ==========
Empresa   Ticker   Preço  Estimativa
========= ======= ======= ==========
Alphabet  GOOG    1030    1330
Amazon    AMZN    1573    1675
Apple     AAPL    162     193 
Facebook  FB      174     216 
Netflix   NFLX    312     327
========= ======= ======= ==========</code></pre><p>Para simplificar o exemplo, vamos supor que você nunca colocaria todos os seus ovos na mesma cesta. Você está disposto(a) a comprar <strong><strong>n</strong>ão<strong> m</strong>ais</strong> do que uma ação de cada. Quais ações você compra para maximizar seu lucro?</p><p>Esse é um problema da mochila. Seu orçamento (R$ 1.600) é a <strong><strong>capaci</strong>dade<strong> (C)</strong></strong> de armazenamento. As ações são os itens a serem embalados. Os preços atuais são os <strong>p<strong>es</strong>os<strong> (w)</strong></strong>. As estimativas de preços são os <strong><strong>val</strong>or<strong>es</strong></strong>. O problema parece trivial. No entanto, a solução não é evidente à primeira vista – se você deve comprar uma ação da Amazon, ou uma ação do Google mais uma de alguma combinação de Apple, Facebook, ou Netflix.</p><p>Claro que, nesse caso, você pode fazer cálculos rápidos à mão e chegar na solução: você deve comprar Google, Netflix, e Facebook. Desse modo, você gasta R$ 1.516 e espera ganhar R$ 1.873.</p><p>Agora, você acredita que descobriu uma mina de outro. Você destrói seu cofrinho e recebe R$ 10.000. Apesar de sua empolgação, você permanece inflexível com a regra "uma ação – uma compra". Portanto, com esse orçamento maior, você tem que ampliar suas opções. Você decide considerar todas as 100 ações da lista da NASDAQ como candidatas para compra.</p><p>O futuro nunca foi tão brilhante, mas, de repente, você percebe que, para identificar sua carteira de investimentos ideal, você terá que verificar cerca de 2¹⁰⁰ combinações. Mesmo que você seja superotimista com a iminência e a onipresença da economia digital, qualquer economia requer — no mínimo — um universo onde funcione. Infelizmente, em alguns trilhões de anos, quando sua computação terminar, nosso universo provavelmente não existirá.</p><h4 id="algoritmo-de-programa-o-din-mica"><strong>Algoritmo de programação dinâmica</strong></h4><p>Temos que abandonar a abordagem de força bruta e programar alguma solução inteligente. Pequenos problemas de mochila (e o nosso é pequeno, acredite ou não) são resolvidos por programação dinâmica. A ideia básica é partir de um problema trivial cuja solução conhecemos e depois adicionaremos complexidade passo a passo.</p><p>Se você achar as explicações a seguir muito abstratas, aqui está uma <a href="https://github.com/mmamaev/looping_python/blob/master/ks_dp_example.pdf" rel="noopener">ilustração comentada</a> da solução para um problema de mochila bem pequeno. Isso ajudará você a visualizar o que está acontecendo.</p><p>Suponha que, dados os primeiros<strong> </strong>itens <strong><strong>i</strong></strong> da coleção, nós saibamos os valores de solução <strong><strong>s(i, k)</strong> </strong>para todas as capacidades de mochila <strong><strong>k</strong></strong> no intervalo de 0 a <strong><strong>C</strong></strong>.</p><p>Em outras palavras, costuramos mochilas "auxiliares" <strong><strong>C+1</strong></strong> de todos os tamanhos de 0 a <strong><strong>C</strong></strong>. Em seguida, organizamos nossa coleção, pegamos o primeiro item <strong><strong>i</strong> </strong>e temporariamente separamos todo o resto. E agora assumimos que, por alguma mágica, nós sabemos como embalar de maneira ideal cada um dos pacotes desse conjunto funcional de <strong><strong>i</strong></strong> itens. Os itens que escolhemos do conjunto funcional podem ser diferentes para pacotes diferentes, mas no momento não estamos interessados em quais itens pegamos ou pulamos. É apenas o valor da solução <strong><strong>s(i, k)</strong></strong> que registramos para cada um de nosso pacotes recém costurados.</p><p>Agora, buscamos o próximo item <strong><strong>(i+1)</strong></strong>º da coleção e adicionamos ao conjunto funcional. Vamos encontrar valores de solução para todas as mochilas auxiliares com esse novo conjunto funcional. Em outras palavras, nós encontramos <strong><strong>s(i+1, k)</strong> </strong>para todo <strong><strong>k=0..C</strong> </strong>dado <strong><strong>s(i, k)</strong></strong>.</p><p>Se <strong><strong>k</strong></strong> for menor que o peso do novo item <strong><strong>w[i+1]</strong></strong>, não podemos pegar esse item. De fato, mesmo que pegássemos <strong>apenas</strong><em><em> </em></em>esse item, ele sozinho não caberia na mochila. Portanto, <strong><strong>s(i+1, k) = s(i, k)</strong></strong> para todo <strong>k &lt; w[i+1]</strong>.</p><p>Para os valores <strong>k &gt;= w[i+1]</strong> temos que fazer uma escolha: ou colocamos o novo item na mochila de capacidade <strong>k</strong> ou o pulamos. Temos que avaliar essas duas opções para determinar qual delas nos dá mais valor embalado no pacote.</p><p>Se pegarmos o <strong><strong>(i+1)</strong></strong>º item, adquirimos o valor <strong><strong>v[i+1]</strong></strong> e consumimos a parte da capacidade da mochila para acomodar o peso <strong><strong>w[i+1]</strong></strong>. Isso nos deixa com a capacidade <strong><strong>k–w[i+1]</strong></strong><em><em> </em></em>que devemos preencher de modo otimizado usando (alguns dos) primeiros<em> </em><strong><strong>i</strong></strong> itens. Esse preenchimento otimizado tem o valor de solução <strong><strong>s(i, k–w[i+1])</strong></strong>. Esse número já é conhecido por nós porque, por suposição, conhecemos todos os valores de solução para o conjunto funcional de <strong><strong>i</strong></strong> itens. Portanto, o valor da solução candidata para a mochila <strong><strong>k</strong></strong> com o item <strong><strong>i+1</strong></strong> levado seria<br><strong><strong>s(i+1, k | i+1 </strong>levado<strong>) = v[i+1] + s(i, k–w[i+1])</strong></strong>.</p><p>A outra opção seria pular o item <strong>i+1</strong>. Nesse caso, nada muda em nossa mochila, e o valor da solução candidata seria o mesmo que <strong>s(i, k)</strong>.</p><p>Para decidir sobre a melhor opção, comparamos os dois candidatos para os valores da solução:</p><p><strong><strong>s(i+1, k | i+1 </strong>levado<strong>) = v[i+1] + s(i, k–w[i+1])</strong></strong><br><strong><strong>s(i+1, k | i+1 </strong>ignorado<strong>) = s(i, k)</strong></strong></p><p>O máximo destes torna-se a solução <strong><strong>s(i+1, k)</strong></strong>.</p><p>Resumindo:</p><pre><code>if k &lt; w[i+1]:
	s(i+1, k) = s(i, k)
else:
	s(i+1, k) = max( v[i+1] + s(i, k-w[i+1]), s(i, k) )</code></pre><p>Agora, podemos resolver o problema da mochila passo a passo. Começamos com o conjunto de trabalho vazio <strong><strong>(<em><em>i=0</em></em>)</strong></strong>. Obviamente, <strong><strong>s(0, k) = 0</strong> </strong>para qualquer <strong><strong>k</strong></strong>. Em seguida, avançamos adicionando itens ao conjunto de trabalho e encontrando os valores de solução <strong><strong>s(i, k)</strong> </strong>até chegarmos a <strong><strong>s(i+1=N, k=C)</strong></strong>, que é o valor de solução do problema original.</p><p>Observe que, ao fazer isso, construímos a grade de valores da solução <strong><strong><em><em>NxC</em></em></strong></strong>.</p><p>No entanto, apesar de ter aprendido o valor da solução, não sabemos exatamente quais itens foram colocados na mochila. Para descobrir isso, retrocedemos a grade. Partindo de <strong><strong>s(i=N, k=C)</strong></strong>, comparamos <strong><strong>s(i, k)</strong></strong> com<strong><strong> s(i–1, k)</strong></strong>.</p><p>Se <strong><strong>s(i, k) = s(i–1, k)</strong></strong>, o <strong><strong>i</strong></strong>-ésimo item não foi considerado. Nós reiteramos com <strong><strong>i=i–1</strong></strong> mantendo o valor de <strong><strong>k</strong></strong> inalterado. Caso contrário, o <strong><strong>i</strong></strong>-ésimo item foi retirado e, para a próxima etapa de exame, encolhemos a mochila em <strong><strong>w[i] </strong></strong>— definimos <strong><strong>i=i–1, k=k–w[i]</strong></strong>.</p><p>Desse modo, examinamos todos os itens do <strong><strong>N</strong></strong>-ésimo ao primeiros e determinamos quais deles foram colocados na mochila. Isso nos dá a solução para o problema da mochila.</p><h3 id="c-digo-e-an-lise"><strong><strong>C</strong>ódigo e análise</strong></h3><p>Como temos o algoritmo, vamos comparar várias implementações, começando por uma simples. O código está disponível no <a href="https://github.com/mmamaev/looping_python/blob/master/ks_dp_solvers.py" rel="noopener">GitHub</a>.</p><p>Os dados são a lista <strong><strong>Nasdaq 100</strong></strong>, contendo preços atuais e estimativas de preços para cem ações (até um dia em 2018). Nosso orçamento de investimento é de R$ 10.000.</p><p>Lembre-se que preços de ações não são números redondos em reais, mas vêm com centavos. Portanto, para obter a solução exata, temos que contar tudo em centavos — definitivamente queremos evitar números float. Portanto, a capacidade de nossa mochila é ($)10.000 x 100 centavos = ($)1.000.000, e o tamanho total de nosso problema <strong><strong>N x C</strong></strong> = 1.000.000.</p><p>Com um inteiro ocupando 4 bytes de memória, esperamos que o algoritmo vá consumir aproximadamente 400 MB de RAM. Portanto, a memória não será uma limitação. É com o tempo de execução que devemos no preocupar.</p><p>Claro, todas as nossas implementações produzirão a mesma solução. Para referência, o investimento (o peso da solução) é 999930 (R$ 9.999,30) e o retorno esperado (o valor da solução) é 1219475 (R$ 12.194,75). A lista de ações a comprar é bem longa (80 de 100 itens). Você pode obtê-la rodando o código.</p><p>Lembre-se de que <strong>este é um exercício de programação, não um conselho de investimento</strong>. Quando você for ler esse artigo, os preços e as estimativas terão mudado em relação ao que é usado aqui como exemplo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_SEihq9zvMPCd8qLZHaUHIg.jpg" class="kg-image" alt="1_SEihq9zvMPCd8qLZHaUHIg" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/09/1_SEihq9zvMPCd8qLZHaUHIg.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_SEihq9zvMPCd8qLZHaUHIg.jpg 720w" sizes="(min-width: 720px) 720px" width="720" height="480" loading="lazy"><figcaption>Crédito: <a href="https://www.snapwi.re/user/mavoro" rel="noopener ugc nofollow">Martin von Rotz</a></figcaption></figure><h4 id="os-bons-e-velhos-loops-do-tipo-for"><strong>Os bons e velhos<strong> l</strong>oops<strong> </strong>do tipo "<strong>for</strong>"</strong></h4><p>A implementação direta do algoritmo é dada abaixo.</p><pre><code>def solve_naive(capacity, items, weights, values):

    grid = [[0] * (capacity+1)]
    for item in range(items):
        grid.append(grid[item].copy())
        for k in range(weights[item], capacity+1):
            grid[item + 1][k] = max(grid[item][k], grid[item][k-weights[item]] + values[item])

    solution_value = grid[items][capacity]
    solution_weight = 0
    taken = []
    k = capacity
    for item in range(items, 0, -1):
        if grid[item][k] != grid[item-1][k]:
            taken.append(item - 1)
            k -= weights[item - 1]
            solution_weight += weights[item-1]

    return solution_value, solution_weight, taken</code></pre><p>Existem duas partes.</p><p>Na primeira parte (linhas 3-7 acima), dois loops <code>for</code> aninhados são usados para construir a grade da solução.</p><p>O loop externo adiciona itens ao conjunto de trabalho até atingirmos <strong><strong>N</strong></strong><em><em> </em></em>(o valor de <strong><strong>N</strong></strong><em><em> </em></em>é passado no parâmetro <code>items</code>). A linha de valores de solução para cada novo conjunto de trabalho é inicializada com os valores calculados para o conjunto de trabalho anterior.</p><p>O loop interno para cada conjunto de trabalho itera os valores de <code>k</code> do peso do <code>item</code> recém adicionado a <strong><strong>C</strong></strong> (o valor de <strong><strong>C</strong></strong><em><em> </em></em>é passado no parâmetro <code>capacity</code>).</p><p>Note que não precisamos iniciar o loop de <strong><strong>k=0</strong></strong><em><em>. </em></em>Quando <code>k</code><em><em> </em></em>é menor do que o peso do<em> </em><code>item</code>, os valores da solução são sempre os mesmos calculados para o conjunto de trabalho anterior. Esses números já foram copiados para a linha atual pela inicialização.</p><p>Quando os loops são concluídos, temos a grade e o valor da solução.</p><p>A segunda parte (linhas 9-17) é um único loop <code>for</code> de <strong><strong>N</strong></strong><em><em> </em></em>iterações. Ele retrocede a grade para descobrir quais itens foram levados pela mochila.</p><p>Mais adiante, nos concentraremos exclusivamente na primeira parte do algoritmo, já que este possui complexidade de tempo e espaço <strong><strong>O(N*C)</strong></strong>. A parte de retrocesso requer apenas tempo <strong><strong>O(N)</strong> </strong>e não gasta nenhuma memória adicional – seu consumo de recursos é relativamente insignificante.</p><p>A implementação direta leva <strong><strong>180 </strong>segundos</strong> para resolver o problema da mochila <strong><strong>Nasdaq 100</strong></strong> no meu computador.</p><p>Isso é muito ruim? Por um lado, com as velocidades da era moderna, não estamos acostumados a passar três minutos esperando que um computador faça as coisas. Por outro lado, o tamanho do problema - cem milhões - parece realmente intimidador, então, talvez, três minutos seja ok?</p><p>Para obter algum <em>benchmark</em>, vamos programar o mesmo algoritmo em outra linguagem. Precisamos de uma linguagem compilada estaticamente tipada para garantir a velocidade de computação. Não, não C. Não é chique. Vamos seguir a moda e escrever em Go:</p><pre><code>func solver(capacity, items int, weights, values []int) (int, int, []int) {
    
    grid :=  make([][]int, items+1, items+1)
    grid[0] = make([]int, capacity+1, capacity+1) 

    for item := 0; item &lt; items; item++ {

        grid[item+1] = make([]int, capacity+1, capacity+1)
        for k:=0; k&lt;weights[item]; k++ {
            grid[item + 1][k] = grid[item][k]
        }
        for k:=weights[item]; k &lt;= capacity; k++ {
            grid[item + 1][k] = max(grid[item][k], grid[item][k-weights[item]] + values[item])
        }
    } 

    solution_value := grid[items][capacity]
    solution_weight := 0
    var taken []int
    k := capacity
    for item := items; item &gt; 0; item-- {
        if grid[item][k] != grid[item-1][k] {
            taken = append(taken, item-1)
            k -= weights[item - 1]
            solution_weight += weights[item-1]
        }
    }

    return solution_value, solution_weight, taken
}</code></pre><p>Como você pode ver, o código Go é bem similar ao do Python. Até copiei e colei uma linha, a mais longa, como está.</p><p>Qual é o tempo de execução? <strong><strong>400</strong> milissegundos</strong>! Em outras palavras, o Python foi 500 vezes mais lento do que o Go. A lacuna provavelmente será ainda maior se tentarmos em C. Isso é definitivamente um desastre para o Python.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_lmi8rlKeei1hcMRkeShzIw.jpg" class="kg-image" alt="1_lmi8rlKeei1hcMRkeShzIw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/09/1_lmi8rlKeei1hcMRkeShzIw.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2023/09/1_lmi8rlKeei1hcMRkeShzIw.jpg 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_lmi8rlKeei1hcMRkeShzIw.jpg 1100w" sizes="(min-width: 720px) 720px" width="1100" height="733" loading="lazy"><figcaption>"Honestamente, se você fosse mais lento, estaria andando para trás." Citação de "Harry Potter e a Câmara Secreta" <a href="https://pixabay.com/en/snail-rainy-day-spring-animal-slow-3385348/" rel="noopener ugc nofollow">Fonte da imagem original</a>.</figcaption></figure><p>Para descobrir o que torna o código Python mais lento, vamos executá-lo com o <a href="https://github.com/rkern/line_profiler" rel="noopener"><em>line profiler</em></a>. Você pode encontrar a saída do <em>profiler </em>para esta implementação e as subsequentes do algoritmo no <a href="https://github.com/mmamaev/looping_python/blob/master/ks_dp_solvers_profiles.txt" rel="noopener">GitHub</a>.</p><p>No solucionador direto, 99,7% do tempo de execução é gasto em duas linhas. Essas duas linhas compõem o loop interno, que é executado 98 milhões de vezes:</p><pre><code>Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    ...
    42       101        170.0      1.7      0.0  for item in range(items):
    43       100    1457275.0  14572.8      0.3      grid.append(grid[item].copy())
    44  98387558  121134401.0      1.2     26.4      for k in range(weights[item], capacity+1):
    45  98387458  336078747.0      3.4     73.3          grid[item + 1][k] = max(grid[item][k], grid[item][k-weights[item]] + values[item])
    ...
</code></pre><p>Peço desculpas pelas linhas excessivamente longas, mas o <em>line profiler</em> não pode lidar adequadamente com quebras de linha na mesma instrução.</p><p>Ouvi dizer que o operador <code>for</code> do Python é lento, mas, curiosamente, a maior parte do tempo não é gasta na linha <code>for</code> mas no corpo do <em>loop</em>.</p><p>Podemos dividir o corpo do <em>loop </em>em operações individuais para ver se alguma operação específica é muito lenta:</p><pre><code>Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    ...
    67       101        196.0      1.9      0.0      for item in range(items):
    68       100    1454886.0  14548.9      0.2          grid.append(grid[item].copy())
    69       100       1463.0     14.6      0.0          wi = weights[item]
    70       100        323.0      3.2      0.0          vi = values[item]
    71  98387558  133663554.0      1.4     16.7          for k in range(wi, capacity+1):
    72  98387458  156110242.0      1.6     19.4              a = grid[item][k]
    73  98387458  194935490.0      2.0     24.3              b = grid[item][k-wi] + vi
    74  98387458  138902753.0      1.4     17.3              if b &gt; a:
    75  60782758  109728042.0      1.8     13.7                  grid[item + 1][k] = b
    76                                                       else:
    77  37604700   67944391.0      1.8      8.5                  grid[item + 1][k] = a
    ...</code></pre><p>Parece que nenhuma operação em particular se destaca. Os tempos de execução das operações individuais dentro do <em>loop </em>interno são praticamente os mesmos que os tempos de execução de operações análogas em outras partes do código.</p><p>Observe como quebrar o código aumentou o tempo total de execução. O <em>loop </em>interno agora leva 99,9% do tempo de execução. Quanto mais burro seu código Python, mais lento ele fica. Interessante, não é?</p><h4 id="fun-o-map-integrada"><strong>Função<strong> <em>map </em></strong>integrada</strong></h4><p>Vamos tornar o código mais otimizado e substituir o <em>loop </em><code>for</code> interno por uma função <code>map()</code> integrada:</p><pre><code>def solve_map(capacity, items, weights, values):
  
    grid = [[0] * (capacity+1)]
    for item in range(items):
        grid.append(grid[item].copy())
        this_weight = weights[item]
        this_value = values[item]
        
        grid[item+1][this_weight:] = 
            list(map(lambda k: max(grid[item][k], 
                                   grid[item][k - this_weight] + this_value), 
                     range(this_weight, capacity+1)))
        
    solution_value = grid[items][capacity]
    solution_weight = 0
    taken = []
    k = capacity
    for item in range(items, 0, -1):
        if grid[item][k] != grid[item-1][k]:
            taken.append(item - 1)
            k -= weights[item - 1]
            solution_weight += weights[item-1]

    return solution_value, solution_weight, taken</code></pre><p>O tempo de execução desse código é de <strong>102 segundos</strong>, estando 78 segundos abaixo da pontuação da implementação direta. De fato, <code>map()</code> é executado visivelmente, mas não excessivamente, mais rápido.</p><h4 id="list-comprehension"><strong><strong><em>List comprehension</em></strong></strong></h4><p>Você deve ter notado que cada execução do <em>loop </em>interno produz uma lista (que é adicionada à grade de solução como uma nova linha). O jeito do Python de criar listas é, claro, <em>list comprehension</em>. Vamos tentar isso, em vez de <code>map()</code>.</p><pre><code>def solve_list_comp(capacity, items, weights, values):

    grid = [[0] * (capacity+1)]
    for item in range(items):
        grid.append(grid[item].copy())
        this_weight = weights[item]
        this_value = values[item]
        
        grid[item+1][this_weight:] = 
            [max(grid[item][k], grid[item][k - this_weight] + this_value) 
             for k in range(this_weight, capacity+1)]
        
    solution_value = grid[items][capacity]
    solution_weight = 0
    taken = []
    k = capacity
    for item in range(items, 0, -1):
        if grid[item][k] != grid[item-1][k]:
            taken.append(item - 1)
            k -= weights[item - 1]
            solution_weight += weights[item-1]

    return solution_value, solution_weight, taken</code></pre><p>O programa terminou em <strong><strong>81 se</strong>gu<strong>nd</strong>o<strong>s</strong></strong>. Conseguimos outra melhoria e reduzimos o tempo de execução pela metade em comparação à implementação direta (180 s). Fora de contexto, isso seria elogiado como um progresso significativo. Infelizmente, ainda estamos a anos-luz do nosso <em>benchmark</em> de 0,4 s.</p><h4 id="arrays-do-numpy"><strong>Arrays do <strong>NumPy</strong></strong></h4><p>Por fim, esgotamos as ferramentas integradas do Python. Sim, posso ouvir o rugido do público cantando "NumPy! NumPy!" Mas, para apreciar a eficiência do NumPy, devemos colocá-lo em contexto, tentando <code>for</code>, <code>map()</code> e <em>list comprehension</em> de antemão.</p><p>Ok, agora é a hora do NumPy. Então, abandonamos as listas e colocamos nossos dados em <em>arrays</em> do NumPy:</p><pre><code>def solve_list_comp_numpy(capacity, items, weights, values):

    grid = np.empty((items + 1, capacity + 1), dtype=int)
    grid[0] = 0
    for item in range(items):
        grid[item+1] = grid[item]
        this_weight = weights[item]
        this_value = values[item]
        
        grid[item+1, this_weight:] = 
            [max(grid[item, k], grid[item, k - this_weight] + this_value) 
             for k in range(this_weight, capacity+1)]

    solution_value = grid[items, capacity]
    solution_weight = 0
    taken = []
    k = capacity
    for item in range(items, 0, -1):
        if grid[item, k] != grid[item-1, k]:
            taken.append(item - 1)
            k -= weights[item - 1]
            solution_weight += weights[item-1]

    return solution_value, solution_weight, taken</code></pre><p>De repente, o resultado é desencorajador. Este código é executado 1,5 vezes mais devagar do que a solução sem graça por <em>list comprehension</em> (<strong><strong>123 s</strong></strong> em comparação com os 81 s). Como isso?</p><p>Vamos examinar os perfis de linha para ambos solucionadores.</p><pre><code>Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
Vanilla list comprehension

   245         1       8212.0   8212.0      0.0  grid = [[0] * (capacity+1)]
   246
   247       101       1654.0     16.4      0.0  for item in range(items):
   248       100    1452204.0  14522.0      0.7      grid.append(grid[item].copy())
   249       100       1603.0     16.0      0.0      this_weight = weights[item]
   250       100        272.0      2.7      0.0      this_value = values[item]
   251
   252       100  202696910.0 2026969.1     99.3     grid[item+1][this_weight:] = [max(grid[item][k], grid[item][k - this_weight] + this_value) for k in range(this_weight, capacity+1)]

Using numpy arrays

   273         1         42.0     42.0      0.0  grid = np.empty((items + 1, capacity + 1), dtype=int)
   274         1       2527.0   2527.0      0.0  grid[0] = 0
   275       101       1427.0     14.1      0.0  for item in range(items):
   276       100     322952.0   3229.5      0.1      grid[item+1] = grid[item]
   277       100       1341.0     13.4      0.0      this_weight = weights[item]
   278       100        266.0      2.7      0.0      this_value = values[item]
   279       100  311244493.0 3112444.9     99.9     grid[item+1, this_weight:] = [max(grid[item, k], grid[item, k - this_weight] + this_value) for k in range(this_weight, capacity+1)]
</code></pre><p>A inicialização do <code>grid[0]</code> como um <em>array</em> do NumPy (linha 274) é três vezes mais rápida do que quando é feita com uma lista do Python (linha 245). Dentro do <em>loop </em>externo, a inicialização do <code>grid[item+1]</code> é 4,5 vezes mais rápida para um <em>array </em>do NumPy (linha 276) do que para uma lista (linha 248). Até agora, tudo bem.</p><p>No entanto, a execução da linha 279 é 1,5 vezes mais lenta do que seu análogo sem o NumPy na linha 252. O problema é que <em>list comprehension </em>cria uma <strong>lista</strong> de valores, mas armazenamos esses valores em um <strong>array do NumPy</strong> que é encontrado no lado esquerdo da expressão. Portanto, essa linha adiciona implicitamente uma sobrecarga de conversão de uma lista em um <em>array</em> do NumPy. Com a linha 279 respondendo por 99,9% do tempo de execução, todas as vantagens do NumPy observadas anteriormente tornam-se insignificantes.</p><p>Ainda precisamos, porém, de uma maneira de<strong> iterar </strong>por meio de <em>arrays </em>para fazer cálculos. Já aprendemos que <em>list comprehension </em>é a ferramenta de iteração mais rápida. A propósito, se você tentar construir um <em>array </em>do NumPy dentro de um bom e velho <em>loop </em><code>for</code>, evitando a conversão de lista para <em>array</em> do NumPy, obterá o impressionante tempo de execução de 295 segundos. Então, estamos travados e o NumPy é inútil? Claro que não.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_0yrZox6O3EEEKregnri0Vw.jpg" class="kg-image" alt="1_0yrZox6O3EEEKregnri0Vw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/09/1_0yrZox6O3EEEKregnri0Vw.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_0yrZox6O3EEEKregnri0Vw.jpg 720w" sizes="(min-width: 720px) 720px" width="720" height="480" loading="lazy"><figcaption>Crédito: <a href="https://www.pexels.com/@taras-makarenko-188506" rel="noopener ugc nofollow">Taras Makarenko</a></figcaption></figure><h4 id="uso-adequado-do-numpy"><strong>Uso adequado do<strong> NumPy</strong></strong></h4><p>Apenas armazenar dados em <em>arrays </em>do NumPy não adianta. O verdadeiro poder do NumPy vem com as funções que executam cálculos em <em>arrays </em>do NumPy. Elas pegam <em>arrays </em>como parâmetros e retornam <em>arrays </em>como resultados.</p><p>Por exemplo, existe a função <code>where()</code>, que recebe três <em>arrays </em>como parâmetros: <code>condition</code>, <code>x</code>, e <code>y</code>, e retorna um <em>array </em>construído pela seleção de elementos de <code>x</code> ou de <code>y</code>. O primeiro parâmetro, <code>condition</code>, é um <em>array</em> de booleanos. Ele diz de onde escolher: se um elemento de <code>condition</code> for avaliado como <code>True</code>, o elemento correspondente de <code>x</code> é enviado para a saída, caso contrário, o elemento de <code>y</code> é selecionado.</p><p>Observe que a função do NumPy faz tudo isso em uma única chamada. Percorrer os <em>arrays </em>passa a ser um processo integrado.</p><p>É assim que usamos <code>where()</code> como um substituto do <em>loop </em><code>for</code> interno no primeiro solucionador ou, respectivamente, o <em>list comprehension</em> do último:</p><pre><code>def solve_numpy_func(capacity, items, weights, values):

    grid = np.empty((items + 1, capacity + 1), dtype=int)
    grid[0] = 0
    for item in range(items):
        this_weight = weights[item]
        this_value = values[item]
        grid[item+1, :this_weight] = grid[item, :this_weight]
        temp = grid[item, :-this_weight] + this_value
        grid[item + 1, this_weight:] = 
            np.where(temp &gt; grid[item, this_weight:], 
                     temp, 
                     grid[item, this_weight:])

    solution_value = grid[items, capacity]
    solution_weight = 0
    taken = []
    k = capacity
    for item in range(items, 0, -1):
        if grid[item][k] != grid[item - 1][k]:
            taken.append(item - 1)
            k -= weights[item - 1]
            solution_weight += weights[item-1]

    return solution_value, solution_weight, taken</code></pre><p>Existem três trechos de códigos interessantes: linha 8, linha 9 e linhas 11-13, conforme numeradas acima. Juntas, elas substituem o <em>loop </em>interno que percorreria todos os tamanhos possíveis de mochilas para encontrar os valores da solução.</p><p>Até que a capacidade da mochila atinja o peso do item recém adicionado ao conjunto de trabalho (<code>this_weight</code>), devemos ignorar esse item e definir os valores da solução para os do conjunto de trabalho anterior. Isso é bastante direto (linha 8):</p><pre><code>grid[item+1, :this_weight] = grid[item, :this_weight]</code></pre><p>Em seguida, construímos um <em>array </em>auxiliar <code>temp</code> (linha 9):</p><pre><code>temp = grid[item, :-this_weight] + this_value</code></pre><p>Esse código é análogo, mas muito mais rápido do que:</p><pre><code>[grid[item, k — this_weight] + this_value
for k in range(this_weight, capacity+1)]</code></pre><p>Ele calcula possíveis valores de solução se o novo item for levado para cada uma das mochilas que podem acomodar esse item.</p><p>Observe como o <em>array </em><code>temp</code> é construído adicionando um <strong>escalar </strong>a um <em>array</em>. Esse é outro recurso poderoso do NumPy chamado "<em>broadcasting</em>". Quando o NumPy vê operandos com dimensões diferentes, ele tenta expandir (ou seja, "transmitir" – em inglês, <em>broadcast</em>) o operando de baixa dimensão para corresponder às dimensões do outro. Em nosso caso, o escalar é expandido para um <em>array </em>do mesmo tamanho que <code>grid[item, :-this_weight]</code> e esses dois <em>arrays </em>são somados. Como resultado, o valor de <code>this_value</code> é adicionado a cada elemento de <code>grid[item, :-this_weight]</code> — nenhum <em>loop </em>é necessário.</p><p>Na próxima parte (linhas 10–13), usamos a função <code>where()</code>, que faz exatamente o que é exigido pelo algoritmo: compara dois possíveis valores de solução para cada tamanho de mochila e seleciona aquele que é maior.</p><pre><code>grid[item + 1, this_weight:] =             
    np.where(temp &gt; grid[item, this_weight:],
             temp,
             grid[item, this_weight:])</code></pre><p>A comparação é feita pelo parâmetro <code>condition</code>, que é calculado como <code>temp &gt; grid[item, this_weight:]</code>. Essa é uma operação elementar que produz um <em>array </em>de valores booleanos, um para cada tamanho de uma mochila auxiliar. Um valor <code>True</code> significa que o item correspondente deve ser colocado na mochila. Portanto, o valor da solução obtido do <em>array </em>é o segundo argumento da função <code>temp</code>. Caso contrário, o item deve ser ignorado, e o valor da solução é copiado da linha anterior da grade - o terceiro argumento da função <code>where()</code>.</p><p>Por fim, o motor de dobra foi ativado! Esse solucionador é executado em <strong>0,55 s</strong>. Isso é 145 vezes mais rápido que o solucionador baseado em <em>list comprehension </em>e 329 vezes mais rápido que o código utilizando o <em>loop </em><code>for</code>. Embora não tenhamos ultrapassado o solucionador escrito em Go (0,4 s), chegamos bem perto disso.</p><h4 id="alguns-loops-s-o-pra-ficar"><strong>Alguns <em>loops </em>são pra ficar</strong></h4><p>Espere, mas e o <em>loop </em><code>for</code> externo?</p><p>Em nosso exemplo, o código do <em>loop </em>externo, que não faz parte do <em>loop </em>interno, é executado apenas 100 vezes, para que possamos escapar sem mexer nele. No entanto, outras vezes, o <em>loop </em>externo pode ser tão longo quanto o interno.</p><p>Podemos reescrever o <em>loop </em>externo usando uma função do NumPy de maneira semelhante ao que fizemos para o <em>loop </em>interno? A resposta é não.</p><p>Apesar de ambos serem <em>loops </em><code>for</code>, os <em>loops </em>externo e interno são bem diferentes no que fazem.</p><p>O <em>loop </em>interno produz um <em>array </em>1D baseado em outro<em> array </em>1D cujos elementos são <strong>todos conhecidos</strong> quando o <em>loop </em>começa. É essa disponibilidade prévia dos dados de entrada que nos permitiu substituir o <em>loop </em>interno por <code>map()</code>, <em>list comprehension</em> ou uma função do NumPy.</p><p>O <em>loop </em>externo produz um <em>array </em>2D a partir de um<em> array </em>1D, cujos elementos <strong>não</strong> são conhecidos quando o <em>loop </em>começa. Além disso, esses componentes de <em>arrays </em>são calculados por um algoritmo recursivo: podemos encontrar os elementos <strong><strong>(i+1)</strong></strong>º do <em>array </em>somente depois de encontrarmos o <strong><strong>i</strong></strong>º.</p><p>Suponha que o <em>loop </em>externo possa ser apresentado como uma função:<br><code>grid = g(row0, row1, … rowN)</code><br>Todos os parâmetros da função devem ser avaliados antes que a função seja chamada, mas somente <code>row0</code> é conhecida de antemão. Como o cálculo da <strong><strong>(i+1)</strong></strong>ª linha depende da disponibilidade da <strong>i</strong>-ésima, precisamos de um <em>loop </em>indo de <code>1</code> a <code>N</code> para calcular todos os parâmetros da linha. Portanto, para substituir o <em>loop </em>externo com uma função, precisamos de outro <em>loop </em>que avalie os parâmetros dessa função. Esse outro <em>loop </em>é exatamente o <em>loop </em>que estamos tentando substituir.</p><p>A outra maneira de evitar o <em>loop </em><code>for</code> externo é usar recursão. Pode-se facilmente escrever a função recursiva <code>calculate(i)</code> que produz a <strong>i</strong>-ésima linha da grade. Para fazer o trabalho, a função precisa conhecer a<strong> (i-1)</strong>ª linha, portanto, chama a si mesma como <code>calculate(i-1)</code> e, em seguida, calcula a <strong>i</strong>-ésima linha usando as funções do NumPy como fizemos anteriormente. Todo o <em>loop </em>externo pode então ser substituído por <code>calculate(N)</code>. Para tornar a imagem completa, um solucionador de mochila recursivo pode ser encontrado no código-fonte que acompanha este artigo no <a href="https://github.com/mmamaev/looping_python/blob/master/ks_dp_solvers.py" rel="noopener">GitHub</a>.</p><p>No entanto, a abordagem recursiva claramente não é escalável. O Python não é otimizado para a <a href="https://pt.wikipedia.org/wiki/Recursividade_(ci%C3%AAncia_da_computa%C3%A7%C3%A3o)#Fun%C3%A7%C3%B5es_recursivas_em_cauda">recursão de cauda</a>. A profundidade da pilha de recursão é, por padrão, limitada pela ordem de mil. Esse limite é certamente conservador, mas, quando exigimos uma profundidade de milhões, o estouro da pilha é altamente provável. Além disso, o experimento mostra que a recursão nem mesmo fornece uma vantagem de desempenho sobre um solucionador baseado em NumPy com o <em>loop </em><code>for</code> externo.</p><p>É aqui que esgotamos as ferramentas fornecidas pelo Python e suas bibliotecas (pelo que sei). Se for absolutamente necessário acelerar o <em>loop</em> que implementa um algoritmo recursivo, será preciso recorrer ao Cython, ou a uma versão do Python compilada em JIT, ou a outra linguagem.</p><h3 id="aprendizados"><strong>Aprendizado<strong>s</strong></strong></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_YvnvnzC2wMwZ_EF3qFHBcg.png" class="kg-image" alt="1_YvnvnzC2wMwZ_EF3qFHBcg" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/09/1_YvnvnzC2wMwZ_EF3qFHBcg.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/09/1_YvnvnzC2wMwZ_EF3qFHBcg.png 800w" sizes="(min-width: 720px) 720px" width="800" height="325" loading="lazy"><figcaption>Tempos de execução das soluções do problema da mochila</figcaption></figure><ul><li>Faça cálculos numéricos com as funções do Numpy. Elas são duas ordens de magnitude mais rápidas do que as ferramentas integradas do Python.</li><li>Das ferramentas integradas do Python, <em>list comprehension</em> é mais rápida que <code>map()</code>, que é significativamente mais rápido que <code>for</code>.</li><li>Para algoritmos profundamente recursivos, os <em>loops </em>são mais eficientes do que as chamadas recursivas de funções.</li><li>Você não pode substituir <em>loops </em>recursivos por <code>map()</code>, <em>list comprehension</em> ou uma função do NumPy.</li><li>O código "burro" (dividido em operações elementares) é o mais lento. Use funções e ferramentas integradas.</li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Uma introdução ao Bag of Words e como programá-lo em Python para PLN ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Praveen Dubey Bag of Words (BOW – ou, em português, sacola de palavras) é um método para extrair recursos de documentos de texto. Esses recursos podem ser usados para treinar algoritmos de aprendizado de máquina. Ele cria um vocabulário de todas as palavras únicas que ocorrem em todos ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/uma-introducao-ao-bag-of-words-e-como-programa-lo-em-python-para-nlp/</link>
                <guid isPermaLink="false">643c1b2684d2fb0595fd6453</guid>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Thu, 29 Jun 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/06/1_dcFrKbfBRJzm514gaxp4YA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/an-introduction-to-bag-of-words-and-how-to-code-it-in-python-for-nlp-282e87a9da04/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">An introduction to Bag of Words and how to code it in Python for NLP</a>
      </p><p>Escrito por: Praveen Dubey</p><p>Bag of Words (BOW – ou, em português, sacola de palavras) é um método para extrair recursos de documentos de texto. Esses recursos podem ser usados para treinar algoritmos de aprendizado de máquina. Ele cria um vocabulário de todas as palavras únicas que ocorrem em todos os documentos do conjunto de treinamento.</p><p><strong>Em termos simples<strong>, </strong>é uma coleção de palavras para representar uma frase, com contagem de palavras e, na maioria das vezes, desconsiderando a ordem em que aparecem<strong>.</strong></strong></p><p>O BOW é uma abordagem amplamente utilizada com:</p><ol><li>Processamento de Linguagem Natural</li><li>Recuperação de informações de documentos</li><li>Classificação de documentos</li></ol><p>De modo geral, envolve as seguintes etapas:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/06/qRGh8boBcLLQfBvDnWTXKxZIEAk5LNfNABHF.png" class="kg-image" alt="qRGh8boBcLLQfBvDnWTXKxZIEAk5LNfNABHF" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/06/qRGh8boBcLLQfBvDnWTXKxZIEAk5LNfNABHF.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/06/qRGh8boBcLLQfBvDnWTXKxZIEAk5LNfNABHF.png 797w" sizes="(min-width: 720px) 720px" width="797" height="101" loading="lazy"><figcaption>Limpeza do texto -&gt; Tokenizar -&gt; Criar o vocabulário -&gt; Gerar vetores</figcaption></figure><p><strong>Os vetores gerados podem ser inseridos em seu algoritmo de aprendizado de máquina.</strong></p><p>Vamos começar com um exemplo para entender, pegando algumas frases e gerando vetores para elas.</p><p>Considere as duas frases abaixo.</p><pre><code>1. "John likes to watch movies. Mary likes movies too."</code></pre><pre><code>2. "John also likes to watch football games."</code></pre><p>Essas duas passagens também podem ser representadas com uma coleção de palavras.</p><pre><code>1. ['John', 'likes', 'to', 'watch', 'movies.', 'Mary', 'likes', 'movies', 'too.']</code></pre><pre><code>2. ['John', 'also', 'likes', 'to', 'watch', 'football', 'games']</code></pre><p>Além disso, para cada passagem, remova ocorrências múltiplas da palavra e use a contagem de palavras para representá-la.</p><pre><code>1. {"John":1,"likes":2,"to":1,"watch":1,"movies":2,"Mary":1,"too":1}</code></pre><pre><code>2. {"John":1,"also":1,"likes":1,"to":1,"watch":1,"football":1,"games":1}</code></pre><p>Supondo que essas passagens façam parte de um documento, abaixo consta a frequência combinada de palavras para nosso documento inteiro. Ambas as frases são consideradas.</p><pre><code> {"John":2,"likes":3,"to":2,"watch":2,"movies":2,"Mary":1,"too":1,  "also":1,"football":1,"games":1}</code></pre><p>O vocabulário acima de todas as palavras de um documento, com suas respectivas contagens de palavras, será usado para criar vetores de cada uma das passagens.</p><p><strong>O comprimento do vetor será sempre igual ao tamanho do vocabulário. Neste caso, o comprimento do vetor é 11.</strong></p><p>Para representar nossas frases originais em um vetor, cada vetor é inicializado com zeros — <strong><strong>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</strong></strong></p><p>Isso é seguido por iteração e comparação com cada palavra em nosso vocabulário, incrementando o valor do vetor se a passagem tiver essa palavra.</p><pre><code>John likes to watch movies. Mary likes movies too.[1, 2, 1, 1, 2, 1, 1, 0, 0, 0]</code></pre><pre><code>John also likes to watch football games.[1, 1, 1, 1, 0, 0, 0, 1, 1, 1]</code></pre><p>Por exemplo, na passagem 1, a palavra <code>likes</code> aparece na segunda posição e aparece duas vezes. Assim, o segundo elemento de nosso vetor para a passagem 1 será 2: <strong><strong>[1, 2, 1, 1, 2, 1, 1, 0, 0, 0]</strong></strong></p><p>O vetor é sempre proporcional ao tamanho do nosso vocabulário.</p><p>Um documento grande onde o vocabulário gerado é enorme pode resultar em um vetor com muitos valores 0. Isso é chamado de <strong>vetor es<strong>pars</strong>o</strong>.<em><em> </em></em>Os vetores esparsos exigem mais memória e recursos computacionais durante a modelagem. O grande número de posições ou dimensões pode tornar o processo de modelagem muito desafiador para algoritmos tradicionais.</p><h3 id="programando-nosso-algoritmo-bow"><strong>Programando nosso algoritmo<strong> BOW</strong></strong></h3><p>A entrada para o nosso código será composta de diversas frases. A saída será os vetores.</p><p>O vetor de entrada é este:</p><pre><code>["Joe waited for the train", "The train was late", "Mary and Samantha took the bus", "I looked for Mary and Samantha at the bus station", "Mary and Samantha arrived at the bus station early but waited until noon for the bus"]</code></pre><h4 id="etapa-1-tokenizar-uma-frase"><strong>Eta<strong>p</strong>a<strong> 1: Tokeniz</strong>ar<strong> </strong>um<strong>a </strong>fra<strong>se</strong></strong></h4><p>Vamos começar removendo <em>stopwords </em>das frases.</p><p><em><strong><strong>Stopwords</strong></strong> </em>são palavras que não contêm significância suficiente para serem usadas sem nosso algoritmo. Não gostaríamos que essas palavras ocupassem espaço em nosso banco de dados ou tomassem um tempo valioso de processamento. Para isso, podemos removê-las facilmente armazenando uma lista de palavras que você considere que sejam <em>stopwords</em>.</p><p><strong><strong>Tokeniza</strong>ção<strong> </strong></strong>é o ato de quebrar uma sequência de strings em pedaços como palavras, palavras-chave, frases, símbolos e outros elementos chamados <strong><strong><em>tokens</em></strong></strong>. <em>Tokens</em> podem ser palavras individuais, frases ou até mesmo passagens inteiras. No processo de tokenização, alguns caracteres como sinais de pontuação são descartados.</p><pre><code>def word_extraction(sentence):    ignore = ['a', "the", "is"]    words = re.sub("[^\w]", " ",  sentence).split()    cleaned_text = [w.lower() for w in words if w not in ignore]    return cleaned_text</code></pre><p>Para uma implementação mais robusta de <em>stopwords</em>, você pode usar a biblioteca python <strong><strong>nltk</strong></strong>. Ela possui um conjunto de palavras predefinidas por idioma. Aqui está um exemplo:</p><pre><code>import nltkfrom nltk.corpus import stopwords set(stopwords.words('english'))</code></pre><h4 id="etapa-2-aplicar-tokeniza-o-a-todas-as-frases"><strong>Eta<strong>p</strong>a<strong> 2: A</strong>plicar<strong> tokeniza</strong>ção a todas as frase<strong>s</strong></strong></h4><pre><code>def tokenize(sentences):    words = []    for sentence in sentences:        w = word_extraction(sentence)        words.extend(w)            words = sorted(list(set(words)))    return words</code></pre><p>O método percorre as frases e adiciona a palavra extraída em um vetor. </p><p>A saída do método será:</p><pre><code>['and', 'arrived', 'at', 'bus', 'but', 'early', 'for', 'i', 'joe', 'late', 'looked', 'mary', 'noon', 'samantha', 'station', 'the', 'took', 'train', 'until', 'waited', 'was']</code></pre><h4 id="etapa-3-construir-vocabul-rio-e-gerar-vetores"><strong>Eta<strong>p</strong>a<strong> 3: </strong>Construir vocabulário e gerar vetores</strong></h4><p>Use os métodos definidos nas etapas 1 e 2 para criar o vocabulário do documento e extrair as palavras das frases.</p><pre><code>def generate_bow(allsentences):        vocab = tokenize(allsentences)    print("Word List for Document \n{0} \n".format(vocab));</code></pre><pre><code>for sentence in allsentences:        words = word_extraction(sentence)        bag_vector = numpy.zeros(len(vocab))        for w in words:            for i,word in enumerate(vocab):                if word == w:                     bag_vector[i] += 1                            print("{0}\n{1}\n".format(sentence,numpy.array(bag_vector)))</code></pre><p>Aqui está a entrada definida e a execução do nosso código:</p><pre><code>allsentences = ["Joe waited for the train train", "The train was late", "Mary and Samantha took the bus", "I looked for Mary and Samantha at the bus station", "Mary and Samantha arrived at the bus station early but waited until noon for the bus"]
generate_bow(allsentences)</code></pre><p>Os vetores de saída para cada frase são:</p><pre><code>Resultado:</code></pre><pre><code>Joe waited for the train [0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 2. 0. 1. 0.]</code></pre><pre><code>The train was late [0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 1.]</code></pre><pre><code>Mary and Samantha took the bus [1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 1. 0. 0. 0. 0.]</code></pre><pre><code>I looked for Mary and Samantha at the bus station [1. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0.]</code></pre><pre><code>Mary and Samantha arrived at the bus station early but waited until noon for the bus [1. 1. 1. 2. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1. 0. 0. 0. 1. 1. 0.]</code></pre><p>Como você pode ver, <strong>cada frase foi comparada com nossa lista de palavras gerada na Etapa 1.<strong> </strong>Com base na comparação, o valor do elemento do vetor pode ser incrementado</strong>. Esses vetores podem ser usados em algoritmos de ML para classificação de documentos e previsões.</p><p>Escrevemos nosso código e geramos vetores, mas agora vamos entender um pouco mais sobre o <em>bag of words</em>.</p><h3 id="insights-sobre-o-bag-of-words"><strong><strong>Insights </strong>sobre o<strong> <em>bag of words</em></strong></strong></h3><p>O modelo BOW considera apenas se uma palavra conhecida ocorre em um documento ou não. Não se importa com o significado, contexto e ordem em que aparecem. </p><p>Isso dá a ideia de que documentos semelhantes terão contagens de palavras semelhantes entre si. Em outras palavras, quanto mais semelhantes as palavras em dois documentos, mais semelhantes os documentos podem ser.</p><h3 id="limita-es-do-bow"><strong>Limitações do<strong> BOW</strong></strong></h3><ol><li><strong><strong>S</strong>ignificado semântico:</strong> a abordagem básica do BOW não considera o significado da palavra no documento. Ele ignora completamente o contexto em que ela é usada. A mesma palavra pode ser usada em vários lugares com base no contexto ou em palavras próximas.</li><li><strong>Tamanho do vetor</strong>: Para um documento grande, o tamanho do vetor pode ser enorme, resultando em muitos cálculos e muito tempo. Pode ser necessário ignorar palavras com base na relevância para o seu caso de uso.</li></ol><p>Essa foi uma pequena introdução ao método BOW. O código mostrou como ele funciona de um modo simples. Há muito mais para entender sobre o BOW. Por exemplo, em vez de dividir nossa frase em uma única palavra (1-grama), você pode dividi-la em um par de duas palavras (bigrama ou 2-gramas). Às vezes, a representação em bigramas parece ser muito melhor do que usar 1-grama. Eles podem ser frequentemente representados usando a notação N-grama. Listei alguns artigos de pesquisa na seção de recursos para um conhecimento mais aprofundado.</p><p>Você não precisa codificar o BOW sempre que precisar. Já faz parte de muitos <em>frameworks </em>disponíveis, como o <em>CountVectorizer</em> no <em>sci-kit learn</em>.</p><p>Nosso código anterior pode ser substituído por:</p><pre><code>from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer()X = vectorizer.fit_transform(allsentences)print(X.toarray())</code></pre><p>É sempre bom entender como funcionam as bibliotecas dos <em>frameworks</em>, bem como os métodos por trás delas. Quanto melhor você entender os conceitos, melhor poderá usar os <em>frameworks</em>.</p><p><strong>Agradecemos pela leitura do artigo. O código mostrado está disponível no <a href="https://gist.github.com/edubey/c52a3b34541456a76a2c1f81eebb5f67"><strong></strong></a><strong><a href="https://gist.github.com/edubey/c52a3b34541456a76a2c1f81eebb5f67" rel="noopener">GitHub</a></strong> do autor<strong>.</strong></strong></p><p>Você pode seguir o autor no <a href="https://medium.com/@edubey" rel="noopener">Medium</a>, <a href="https://twitter.com/edubey1" rel="noopener">Twitter</a> e no <a href="https://www.linkedin.com/in/edubey/" rel="noopener">LinkedIn</a>. Para qualquer dúvida, você pode entrar em contato com o autor por <a href="mailto: praveend806@gmail.com">e-mail</a>.</p><h3 id="recursos-para-ler-mais-sobre-bag-of-words-em-ingl-s-"><strong><strong><strong><strong>Re</strong></strong></strong>cursos para ler mais sobre<strong><strong><strong> <em>bag of words</em></strong></strong></strong> (em inglês)</strong></h3><ol><li><a href="https://en.wikipedia.org/wiki/Bag-of-words_model" rel="noopener">Wikipedia-BOW</a></li><li><a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.453.5924&amp;rep=rep1&amp;type=pdf" rel="noopener">Understanding Bag-of-Words Model: A Statistical Framework</a></li><li><a href="https://ieeexplore.ieee.org/document/5428847" rel="noopener">Semantics-Preserving Bag-of-Words Models and Applications</a></li></ol> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como ler uma tabela de regressão ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Sharad Vijalapuram O que é regressão? Regressão é um dos processos de análise de dados mais importantes e comumente usados. Simplificando, é um método estatístico que explica a força da relação entre uma variável dependente e uma ou mais variáveis independentes. Uma variável dependente pode ser uma variável ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-ler-uma-tabela-de-regressao/</link>
                <guid isPermaLink="false">64137b55450cb2052fa76bb4</guid>
                
                    <category>
                        <![CDATA[ Ciência de dados ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Wed, 10 May 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/1_kiLhwgfqplmsa9QgUfXjKQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/https-medium-com-sharadvm-how-to-read-a-regression-table-661d391e9bd7-708e75efc560/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to read a Regression Table</a>
      </p><p>Escrito por: Sharad Vijalapuram</p><h3 id="o-que-regress-o"><strong><strong>O que é regressão<strong><strong>?</strong></strong></strong></strong></h3><p>Regressão é um dos processos de análise de dados mais importantes e comumente usados. Simplificando, é um método estatístico que explica a força da relação entre uma variável dependente e uma ou mais variáveis independentes.</p><p>Uma variável dependente pode ser uma variável ou um campo que você esteja tentando prever ou compreender. Uma variável independente pode ser os campos ou pontos de dados que você acha que podem ter um impacto na variável dependente.</p><p>Ao fazer isso, ela responde algumas questões importantes:</p><ul><li>Quais variáveis importam?</li><li>Até que ponto essas variáveis importam?</li><li>Qual o nível de nossa confiança sobre essas variáveis?</li></ul><h3 id="vamos-ver-um-exemplo-"><strong>Vamos ver um exemplo<strong>…</strong></strong></h3><p>Para explicar melhor os números na tabela de regressão, pensei que seria útil usar um conjuntos de dados como amostra e percorrer os números e sua importância.</p><p>Estou usando um pequeno conjunto dados que contém as pontuações no GRE (um teste que os alunos fazem para serem considerados para admissão em universidades nos EUA) de 500 alunos e suas chances de admissão em uma universidade.</p><p>Como <code>chance de admissão</code> (em inglês, <em>chance of admittance</em>) depende da <code>pontuação no GRE</code> (em inglês, <em>GRE scores</em>), <code>chance de admissão</code> é a variável dependente e <code>pontuação no GRE</code> é a variável independente.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/gEmYfLngh9iyyI1iWPkIHT2H4VGekxpIxUHY.png" class="kg-image" alt="gEmYfLngh9iyyI1iWPkIHT2H4VGekxpIxUHY" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/gEmYfLngh9iyyI1iWPkIHT2H4VGekxpIxUHY.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/gEmYfLngh9iyyI1iWPkIHT2H4VGekxpIxUHY.png 800w" sizes="(min-width: 720px) 720px" width="800" height="438" loading="lazy"><figcaption>Gráfico de dispersão de pontuações no GRE e chance de admissão</figcaption></figure><h4 id="linha-de-regress-o"><strong>Linha de regressão</strong></h4><p>Desenhar uma linha reta que melhor descreva a relação entre as pontuações no GRE de alunos e suas chances de admissão nos fornece a<strong><strong> </strong>linha de regressão linear</strong>. Esta é conhecida como <strong>linha de tendência</strong> em várias ferramentas de <em>Business Intelligence</em> (BI). A ideia básica por trás do desenho dessa linha é minimizar a distância entre os pontos de dados em uma determinada coordenada x e a coordenada y pela qual a linha de regressão passa.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/ZKNDJUJRHA0Es0khr8RpLkbot3QmMPxsMc8Z.png" class="kg-image" alt="ZKNDJUJRHA0Es0khr8RpLkbot3QmMPxsMc8Z" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/ZKNDJUJRHA0Es0khr8RpLkbot3QmMPxsMc8Z.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/ZKNDJUJRHA0Es0khr8RpLkbot3QmMPxsMc8Z.png 800w" sizes="(min-width: 720px) 720px" width="800" height="438" loading="lazy"><figcaption>Gráfico de dispersão com uma linha de regressão.</figcaption></figure><p>A linha de regressão facilita a representação da relação. Ela se baseia em uma equação matemática que associa o coeficiente x e o ponto de interceptação do eixo y.</p><p><strong>y<strong> </strong></strong>é o ponto no qual a linha intercepta o eixo y quando x = 0. Também é o valor que o modelo assumiria ou preveria quando x fosse 0.</p><p><strong><strong>Coef</strong>icientes</strong> fornecem o impacto ou o peso de uma variável em relação a todo o modelo. Em outras palavras, fornecem a quantidade de mudança necessária na variável dependente para que ocorra uma mudança de unidade na variável independente.</p><h4 id="calculando-a-equa-o-da-linha-de-regress-o"><strong><strong>C</strong>alculando a equação da linha de regressão</strong></h4><p>Para descobrir o ponto de interceptação de y do modelo, estendemos a linha de regressão o suficiente para que ela intersecte o eixo y em x = 0. Esse é o nosso ponto de interceptação de y, que está em torno de -2,5. O número pode não fazer sentido para o conjunto de dados em questão, mas a intenção é mostrar apenas o cálculo desse ponto.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/Qr8R9PGFVxf8VnwyQrmaVCpU0PqnAeW3FH9i.png" class="kg-image" alt="Qr8R9PGFVxf8VnwyQrmaVCpU0PqnAeW3FH9i" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/Qr8R9PGFVxf8VnwyQrmaVCpU0PqnAeW3FH9i.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/Qr8R9PGFVxf8VnwyQrmaVCpU0PqnAeW3FH9i.png 800w" sizes="(min-width: 720px) 720px" width="800" height="417" loading="lazy"><figcaption>Calculando o ponto de interceptação de y</figcaption></figure><p>O coeficiente para este modelo será apenas a inclinação da linha de regressão, e pode ser calculado obtendo a mudança na chance de admissão de acordo com a mudança nas pontuações no GRE.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/r8Xzo0fzjJ4HeM-cHz66kST-aW-gTdcqde05.png" class="kg-image" alt="r8Xzo0fzjJ4HeM-cHz66kST-aW-gTdcqde05" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/r8Xzo0fzjJ4HeM-cHz66kST-aW-gTdcqde05.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/r8Xzo0fzjJ4HeM-cHz66kST-aW-gTdcqde05.png 800w" sizes="(min-width: 720px) 720px" width="800" height="430" loading="lazy"><figcaption>Calculando a inclinação</figcaption></figure><p>No exemplo acima, o coeficiente seria apenas</p><blockquote>m = (y2-y1) / (x2-x1)</blockquote><p>Neste caso, seria próximo de 0,01.</p><p>A fórmula y = m*x + b nos ajuda a calcular a equação matemática de nossa linha de regressão. Substituindo os valores do ponto de interceptação de y e da inclinação que obtivemos ao estender a linha de regressão, podemos formular a equação abaixo:</p><blockquote>y = 0,01x — 2,48</blockquote><p>-2,48 é um valor de ponto de interceptação de y mais preciso que obtive da tabela de regressão, conforme mostrado posteriormente neste artigo.</p><p>Essa equação nos permite predizer a chance de admissão de um(a) aluno(a) quando sua pontuação no GRE é conhecida.</p><p>Agora que temos o básico, vamos partir para a leitura e a interpretação de uma tabela de regressão.</p><h3 id="lendo-uma-tabela-de-regress-o"><strong>Lendo uma tabela de<strong> regress</strong>ão</strong></h3><p>A tabela de regressão pode ser dividida em basicamente <strong><strong>t</strong>rês<strong> component</strong>e<strong>s</strong></strong>:</p><ul><li><strong>a<strong>n</strong>álise<strong> </strong>de<strong> </strong>v<strong>ari</strong>â<strong>nc</strong>ia<strong> (ANOVA):</strong></strong> fornece a análise da variância no modelo, como o próprio nome sugere.</li><li><strong>estatísticas de <strong>regress</strong>ão<strong>:</strong></strong> fornecem informações numéricas sobre a variação e sobre a exatidão da explicação do modelo para a variação dos dados/observações fornecidos.</li><li><strong>saída <strong>residual:</strong></strong> fornece o valor previsto pelo modelo e a diferença entre o valor real observado da variável dependente e seu respectivo valor previsto pelo modelo de regressão para cada ponto dos dados.</li></ul><h3 id="an-lise-de-vari-ncia-anova-"><strong><strong><strong><strong>An</strong></strong></strong>álise de variância<strong><strong><strong> (ANOVA)</strong></strong></strong></strong></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/qcL1FHAqajHQ3fk2Qnp2wMjSNDzWAf5vMNYP.png" class="kg-image" alt="qcL1FHAqajHQ3fk2Qnp2wMjSNDzWAf5vMNYP" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/qcL1FHAqajHQ3fk2Qnp2wMjSNDzWAf5vMNYP.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/qcL1FHAqajHQ3fk2Qnp2wMjSNDzWAf5vMNYP.png 800w" sizes="(min-width: 720px) 720px" width="800" height="122" loading="lazy"><figcaption>Tabela ANOVA</figcaption></figure><h4 id="graus-de-liberdade-gl-"><strong>Graus de liberdade<strong> (</strong>gl<strong>)</strong></strong></h4><p>Os <strong>gl da regressão</strong> (em inglês, <em>regression degrees of freedom </em>ou <em>regression df</em>) são o número de variáveis independentes no nosso modelo de regressão. Como consideramos apenas as pontuações no GRE nesse exemplo, seu valor é 1.</p><p>O <strong>gl residual</strong> (em inglês, <em>residual degrees of freedom </em>ou <em>residual df</em>) é o número total de observações (linhas) do conjunto de dados subtraído pelo número de variáveis que estão sendo estimadas. Neste exemplo, tanto o coeficiente de pontuação GRE quanto a constante são estimados.</p><p><strong>gl residual</strong> = 500 — 2 = 498</p><p><strong>gl total<strong> </strong></strong>— é a soma da regressão e dos graus de liberdade residuais, que equivale ao tamanho do conjunto de dados menos 1.</p><h4 id="soma-dos-quadrados-sq-"><strong><strong><strong><strong>S</strong></strong></strong>o<strong><strong><strong>m</strong></strong></strong>a dos quadrados<strong><strong><strong> (</strong></strong></strong>SQ<strong><strong><strong>)</strong></strong></strong></strong></h4><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/9E4FVD77xkpB9bZ2Npwa-Y7jwhlEH6-qzDlh.png" class="kg-image" alt="9E4FVD77xkpB9bZ2Npwa-Y7jwhlEH6-qzDlh" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/9E4FVD77xkpB9bZ2Npwa-Y7jwhlEH6-qzDlh.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/9E4FVD77xkpB9bZ2Npwa-Y7jwhlEH6-qzDlh.png 800w" sizes="(min-width: 720px) 720px" width="800" height="370" loading="lazy"><figcaption>Linha de regressão com a média do conjunto de dados em vermelho.</figcaption></figure><p><strong><strong>S</strong>Q da regressão</strong> (em inglês, <em>regression sum of squares </em>ou <em>regression SS</em>)<strong><strong> </strong></strong>é a variação total da variável dependente que é explicada pelo modelo de regressão. É a soma do quadrado da diferença entre o valor previsto e a média do valor de todos os pontos de dados.</p><blockquote>∑ (ŷ — ӯ)²</blockquote><p>Na tabela ANOVA, a SQ da regressão é 6,5 e a SQ total é 9,9, o que significa que o modelo de regressão explica cerca de 6,5/9,9 (aproximadamente 65%) de toda a variabilidade no conjunto de dados.</p><p><strong>SQ residual</strong> (em inglês, <em>residual sum of squares </em>ou <em>residual SS</em>) é a variação total na variável dependente que não é explicada pelo modelo de regressão. Ela também é chamada de <strong>so<strong>m</strong>a<strong> </strong>d<strong>o</strong>s<strong> </strong>quadrados do erro,</strong> sendo a soma do quadrado da diferença entre valores reais e previstos de todos os pontos de dados.</p><blockquote>∑ (y — ŷ)²</blockquote><p>Na tabela ANOVA, a SQ residual é de cerca de 3,4. Em geral, quanto menor o erro, melhor o modelo de regressão explica a variação no conjunto de dados e, portanto, geralmente queremos minimizar esse erro.</p><p>A <strong>SQ <strong>Total</strong></strong> é a soma de ambas, SQ da regressão e residual, ou por quanto a chance de admissão variaria se as pontuações no GRE <strong><strong>N</strong>ÃO<strong> </strong></strong>fossem levadas em consideração.</p><p><strong>Erros quadráticos médios<strong> (</strong>EQ<strong>M)</strong></strong> — são a média da soma dos quadrados ou a soma dos quadrados dividida pelos graus de liberdade de ambos os casos, regressão e resíduos.</p><blockquote>EQM da regressão = ∑ (ŷ — ӯ)²/Reg. gl</blockquote><blockquote>EQM residual = ∑ (y — ŷ)²/Res. gl</blockquote><p><strong><strong>F</strong></strong> — é usado para testar a hipótese de que a inclinação da variável independente é zero. Matematicamente também pode ser calculado como</p><blockquote>F = EQM da regressão/EQM residual</blockquote><p>Caso contrário, é calculada comparando a estatística F com uma distribuição F com gl de regressão em graus no numerador e gl residual em graus no denominador.</p><p><strong><strong>Signific</strong>â<strong>nc</strong>ia<strong> F </strong></strong>— nada mais é do que o valor-p para a hipótese nula de que o coeficiente da variável independente é zero e, como acontece com qualquer valor-p, um baixo valor-p indica que existe uma relação significativa entre as variáveis dependentes e independentes.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/QeNjs4oji3peiiodEnLof0wx4NSJlu5imm9C.png" class="kg-image" alt="QeNjs4oji3peiiodEnLof0wx4NSJlu5imm9C" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/QeNjs4oji3peiiodEnLof0wx4NSJlu5imm9C.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/QeNjs4oji3peiiodEnLof0wx4NSJlu5imm9C.png 800w" sizes="(min-width: 720px) 720px" width="800" height="86" loading="lazy"></figure><p><strong>Erro padrão<strong> </strong></strong>— fornece o desvio padrão estimado da distribuição dos coeficientes. É a quantidade pela qual o coeficiente varia em diferentes casos. Um coeficiente muito maior que seu erro padrão implica uma probabilidade de que o coeficiente não seja 0.</p><p><strong><strong>t-Stat</strong></strong> é a estatística t ou o valor t do teste, e seu valor é igual ao coeficiente dividido pelo erro padrão.</p><blockquote>t-Stat = coeficientes/erro padrão</blockquote><p>Novamente, quanto maior o coeficiente em relação ao erro padrão, maior é o <em>t-Stat </em>e maior a probabilidade de que o coeficiente esteja longe de 0.</p><p><strong>valor-p</strong> — A estatística t é comparada com a distribuição t para determinar o valor-p. Geralmente, consideramos apenas o valor-p da variável independente, que fornece a probabilidade de obter uma amostra tão próxima daquela usada para derivar a equação de regressão, para verificar se a inclinação da linha de regressão é realmente zero ou se o coeficiente é próximo do coeficiente obtido.</p><p>Um valor-p abaixo de 0,05 indica 95% de confiança de que a inclinação da linha de regressão não é zero e, portanto, existe uma relação linear significativa entre as variáveis dependentes e independentes.</p><p>Um valor-p maior do que 0,05 indica que a inclinação da linha de regressão pode ser zero e que não há evidência suficiente, ao nível de confiança de 95%, da existência de uma relação linear significativa entre as variáveis dependentes e independentes.</p><p>Uma vez que o valor-p da variável independente pontuação no GRE está muito próximo de 0, podemos estar extremamente confiantes da existência de uma relação linear significativa entre as pontuações no GRE e a chance de admissão.</p><p><strong><strong>95%</strong></strong> <strong>inferiores<strong> </strong>e<strong> </strong>su<strong>per</strong>iores<strong> </strong></strong>— Como usamos principalmente uma amostra de dados para estimar a linha de regressão e seus coeficientes, eles são geralmente uma aproximação dos verdadeiros coeficientes e, por conseguinte, da verdadeira linha de regressão. Os limites inferior e superior de 95% fornecem o 95º intervalo de confiança dos limites inferior e superior para cada coeficiente.</p><p>Como o intervalo de confiança de 95% para as pontuações no GRE é 0,009 e 0,01, os limites não contêm zero e, portanto, podemos ter 95% de confiança de que existe uma relação linear significativa entre as pontuações GRE e a chance de admissão.</p><p>Observe que um nível de confiança de 95% é amplamente utilizado, mas um nível diferente de 95% é possível e pode ser configurado durante a análise de regressão.</p><h3 id="estat-sticas-de-regress-o"><strong>Estatísticas de r<strong><strong><strong>egress</strong></strong></strong>ão</strong></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/7zaL2AUSPsdw2T8imw5bAqr6kCOy3nKOeHGk.png" class="kg-image" alt="7zaL2AUSPsdw2T8imw5bAqr6kCOy3nKOeHGk" width="453" height="180" loading="lazy"><figcaption>Tabela de estatísticas de regressão</figcaption></figure><p><strong><strong>R² (R </strong>quadrado<strong>) </strong></strong>— representa o poder de um modelo. Ele mostra a quantidade de variação na variável dependente que é explicada pela variável independente, e sempre fica entre os valores 0 e 1. À medida que o R² aumenta, mais a variação nos dados é explicada pelo modelo e melhor o modelo obtém a previsão. Um R² baixo indicaria que o modelo não se ajusta bem aos dados, e que uma variável independente não explica bem a variação na variável dependente.</p><blockquote>R² = soma dos quadrados da regressão/soma total dos quadrados</blockquote><p>No entanto, o R quadrado <em><em>n</em>ão pode</em> determinar se as estimativas e previsões do coeficiente são tendenciosas. É por isso que você deve analisar os gráficos de resíduos, que são discutidos posteriormente neste artigo.</p><p>O R quadrado também não indica se um modelo de regressão é adequado. Você pode ter um valor R quadrado baixo para um bom modelo, ou um valor R quadrado alto para um modelo que não se ajusta aos dados.</p><p>O R², neste caso, é 65%, o que implica que as pontuações no GRE podem explicar 65% da variação na chance de admissão.</p><p><strong><strong>R²</strong> ajustado</strong> — é o R² multiplicado por um fator de ajuste. Isso é usando ao comparar diferentes modelos de regressão com diferentes variáveis independentes. Esse número é útil ao decidir sobre as variáveis independentes corretas em modelos de regressão múltipla.</p><p><strong><strong>R</strong> múltiplo</strong> — é a raiz quadrada positiva de R²</p><p><strong>Erro padrão</strong> — é diferente do erro padrão dos coeficientes. Este é o desvio padrão estimado do erro da equação de regressão, e é uma boa medida da acurácia da linha de regressão. É a raiz quadrada dos erros quadráticos médios residuais.</p><blockquote>Erro padrão = √(Res.MS)</blockquote><h3 id="sa-da-residual"><strong>Saída residual</strong></h3><p>Resíduos são a diferença entre o valor real e o valor previsto do modelo de regressão. A saída residual é o valor da variável dependente previsto pelo modelo de regressão e o resíduo para cada ponto de dados.</p><p>Como o nome sugere, um gráfico residual é um gráfico de dispersão entre o resíduo e a variável independente, que, neste caso, é a pontuação GRE de cada aluno.</p><p>Um gráfico residual é importante para detectar coisas como <strong><strong>heterocedastici</strong>dade</strong>, <strong>não linearidade </strong>e <strong>valores atípicos </strong>(em inglês, <em>outliers</em>). O processo para detectá-los não está sendo discutido neste artigo, mas o fato de que o gráfico de resíduos para o nosso exemplo possui dados aleatoriamente dispersos nos ajuda a estabelecer o fato de que a relação entre as variáveis neste modelo é linear.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/svhwHtrkIYoNwy323YB8jPS-OxeWmvmpPAyH.png" class="kg-image" alt="svhwHtrkIYoNwy323YB8jPS-OxeWmvmpPAyH" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/svhwHtrkIYoNwy323YB8jPS-OxeWmvmpPAyH.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/svhwHtrkIYoNwy323YB8jPS-OxeWmvmpPAyH.png 800w" sizes="(min-width: 720px) 720px" width="800" height="401" loading="lazy"><figcaption>Gráfico residual</figcaption></figure><h3 id="inten-o"><strong><strong><strong><strong>Inte</strong></strong></strong>nção</strong></h3><p>A intenção deste artigo não é construir um modelo de regressão funcional, mas fornecer um passo a passo de todas as variáveis de regressão e sua importância quando necessário, com a amostra de um conjunto de dados em uma tabela de regressão.</p><p>Embora este artigo forneça uma explicação com uma regressão linear com apenas uma variável como exemplo, esteja ciente de que algumas dessas variáveis podem ter mais importância nos casos de multivariáveis ou outras situações.</p><h3 id="refer-ncias-em-ingl-s-"><strong><strong><strong><strong>R</strong></strong></strong>eferências (em inglês)</strong></h3><ul><li><a href="https://www.kaggle.com/mohansacharya/graduate-admissions" rel="noopener">Graduate Admissions Dataset</a></li><li><a href="https://egap.org/methods-guides/10-things-know-about-reading-regression-table" rel="noopener">10 things about reading a regression table</a></li><li><a href="https://hbr.org/2015/11/a-refresher-on-regression-analysis" rel="noopener">A refresher on regression analysis</a></li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Aprenda a criar seu primeiro bot no Telegram com Python ]]>
                </title>
                <description>
                    <![CDATA[ Imagine ter um bot de mensagens que enviará uma imagem aleatória com um cachorro fofo sempre que você quiser. Parece legal, certo? Vamos fazer um bot desses! Para este tutorial, vamos usar o Python 3, a biblioteca python-telegram-bot [https://github.com/python-telegram-bot/python-telegram-bot] e a API pública  RandomDog [https://random.dog/]. Ao final deste tutorial, ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/aprenda-a-criar-seu-primeiro-bot-no-telegram-com-python/</link>
                <guid isPermaLink="false">63c54c7c91baea05fef7069a</guid>
                
                    <category>
                        <![CDATA[ Bots ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Isabel Cristina Nunes de Sousa ]]>
                </dc:creator>
                <pubDate>Tue, 14 Mar 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/03/1_vUK3nWPkSEJVAFRLLJbxHA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/learn-to-build-your-first-bot-in-telegram-with-python-4c99526765e4/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Learn to build your first bot in Telegram with Python</a>
      </p><p>Imagine ter um bot de mensagens que enviará uma imagem aleatória com um cachorro fofo sempre que você quiser. Parece legal, certo? Vamos fazer um bot desses!</p><p>Para este tutorial, vamos usar o <strong><strong>Python 3</strong></strong>, a biblioteca<strong><strong> <a href="https://github.com/python-telegram-bot/python-telegram-bot" rel="noopener">python-telegram-bot</a> </strong></strong>e a API pública <a href="https://random.dog/" rel="noopener"><strong><strong>RandomDog</strong></strong></a><strong><strong>.</strong></strong></p><p>Ao final deste tutorial, você terá um bot para aliviar o estresse e que enviará imagens fofas de cachorros sempre que você precisar. 😀</p><h3 id="come-ando"><strong>Começando</strong></h3><p>Antes de começarmos a escrever o programa, precisamos gerar um token para nosso bot. O token é necessário para acessar a API do Telegram e instalar as dependências necessárias.</p><h4 id="1-crie-um-bot-no-botfather"><strong><strong>1. Cr</strong>i<strong>e </strong>um <strong>bot </strong>no<strong> BotFather</strong></strong></h4><p>Se você quiser criar um bot no Telegram, primeiro precisa "registrar" seu bot antes de usá-lo. Ao "registrarmos" nosso bot, obteremos o token para acessar a API do Telegram.</p><p>Acesse o <a href="https://telegram.me/BotFather" rel="noopener">BotFather</a> (se for abrir na área de trabalho, certifique-se de que possui o aplicativo do Telegram). Então, crie um bot enviando o comando <code>/newbot</code>. Siga as etapas até obter o nome de usuário e o token para seu bot. Você pode acessar seu bot por meio deste URL: <code><a href="https://telegram.me/YOUR_BOT_USERNAMEa" rel="noopener">https://telegram.me/NOME_DE_USUARIO_DO_SEU_BOT</a></code> e seu token deve ter esta aparência:</p><pre><code>704418931:AAEtcZ*************</code></pre><h4 id="2-instale-a-biblioteca"><strong><strong>2. </strong>Instale a biblioteca</strong></h4><p>Como vamos usar uma biblioteca para este tutorial, instale-a usando este comando:</p><pre><code>pip3 install python-telegram-bot</code></pre><p>Se a biblioteca for instalada com sucesso, estamos prontos.</p><h3 id="escreva-o-programa"><strong>Escreva o programa</strong></h3><p>Vamos fazer nosso primeiro bot. Ele deve retornar uma imagem de cachorro quando enviarmos o comando <code>/bop</code>. Para conseguirmos fazer isso, podemos usar a API pública do <a href="https://random.dog/" rel="noopener"><strong><strong>RandomDog</strong></strong></a><strong><strong> </strong></strong>para nos ajudar a gerar imagens aleatórias de cães.</p><p>O fluxo de trabalho do nosso bot é simples assim:</p><blockquote>acesse a API -&gt; obtenha o URL da imagem -&gt; envie a imagem</blockquote><h4 id="1-importe-as-bibliotecas"><strong><strong>1. Import</strong>e as bibliotecas</strong></h4><p>Primeiro, importamos todas as bibliotecas que precisaremos.</p><pre><code class="language-py">from telegram.ext import Updater, CommandHandler
import requests
import re</code></pre><h4 id="2-acesse-a-api-e-obtenha-o-url-da-imagem"><strong><strong>2. Ac</strong>esse a<strong> API </strong>e obtenha o<strong> URL</strong> da imagem</strong></h4><p>Vamos criar uma função para obter o URL. Usando a biblioteca <code>requests</code>, podemos acessar a API e obter os dados em json.</p><pre><code>contents = requests.get('https://random.dog/woof.json').json()</code></pre><p>Você pode conferir os dados json acessando, pelo seu navegador, este URL: <code>https://random.dog/woof.json</code>. Você verá algo assim em sua tela:</p><pre><code>{“url":"https://random.dog/*****.JPG"}</code></pre><p>Obtenha o URL da imagem, pois precisamos desse parâmetro para conseguir enviar a imagem.</p><pre><code>image_url = contents['url']</code></pre><p>Envolva o código em uma função chamada <code>get_url()</code> .</p><pre><code class="language-py">def get_url():
    contents = requests.get('https://random.dog/woof.json').json()    
    url = contents['url']
    return url</code></pre><h4 id="3-envie-a-imagem"><strong><strong>3. </strong>Envie a <strong>image</strong>m</strong></h4><p>Para enviar uma mensagem/imagem, precisamos de dois parâmetros, o URL da imagem e o ID do destinatário – pode ser o ID de um grupo ou o ID de um usuário.</p><p>Podemos obter o URL da imagem chamando nossa função <code>get_url()</code>.</p><pre><code>url = get_url()</code></pre><p>Obtenha o ID do destinatário usando este código:</p><pre><code>chat_id = update.message.chat_id</code></pre><p>Após conseguirmos o URL da imagem e o ID do destinatário, é hora de enviar a mensagem, que é uma imagem.</p><pre><code>bot.send_photo(chat_id=chat_id, photo=url)</code></pre><p>Envolva o código em uma função chamada <code>bop</code> e certifique-se de que seu código se pareça com isso:</p><pre><code class="language-py">def bop(bot, update):
    url = get_url()
    chat_id = update.message.chat_id
    bot.send_photo(chat_id=chat_id, photo=url)</code></pre><h4 id="4-programa-principal-main-"><strong><strong>4. </strong>Programa principal (<code>main</code>)</strong></h4><p>Por fim, crie outra função chamada <code>main</code> para executar nosso programa. <strong>Não se esqueça de alterar</strong> <code>SEU_TOKEN</code> pelo token que geramos anteriormente neste tutorial.</p><pre><code class="language-py">def main():
    updater = Updater('SEU_TOKEN')
    dp = updater.dispatcher
    dp.add_handler(CommandHandler('bop',bop))
    updater.start_polling()
    updater.idle()
    
if __name__ == '__main__':
    main()</code></pre><p>Ao final, seu código deve ficar assim:</p><pre><code class="language-py">from telegram.ext import Updater, InlineQueryHandler, CommandHandler
import requests
import re

def get_url():
    contents = requests.get('https://random.dog/woof.json').json()    
    url = contents['url']
    return url

def bop(bot, update):
    url = get_url()
    chat_id = update.message.chat_id
    bot.send_photo(chat_id=chat_id, photo=url)

def main():
    updater = Updater('SEU_TOKEN')
    dp = updater.dispatcher
    dp.add_handler(CommandHandler('bop',bop))
    updater.start_polling()
    updater.idle()

if __name__ == '__main__':
    main()</code></pre><h4 id="5-execute-o-programa"><strong><strong>5. </strong>Execute o<strong> program</strong>a</strong></h4><p>Incrível! Você terminou seu primeiro programa. Agora, vamos conferir se funciona. Salve o arquivo, chame-o de <code>main.py</code> e execute-o usando este comando:</p><pre><code>python3 main.py</code></pre><p>Vá até seu bot do telegram acessando este URL: <code><a href="https://telegram.me/YOUR_BOT_USERNAMEa" rel="noopener">https://telegram.me/NOME_DE_USUARIO_DO_SEU_BOT</a></code>. </p><p>Envie o comando <code>/bop</code>. Se tudo funcionar perfeitamente, o bot responderá com uma imagem de cachorro aleatória. Fofo, não é?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/03/cgojJGcVwIVamFkYrpcRzrOOBJ0xFB0cTkTP.jpg" class="kg-image" alt="cgojJGcVwIVamFkYrpcRzrOOBJ0xFB0cTkTP" width="300" height="532" loading="lazy"><figcaption>Uma imagem gerada aleatoriamente</figcaption></figure><h3 id="tratamento-de-erros"><strong>Tratamento de erros</strong></h3><p>Ótimo! Agora, você tem um bot que enviará uma imagem fofa de cachorro sempre que quiser.</p><p>Tem mais! A API <a href="https://random.dog/" rel="noopener"><strong><strong>RandomDog</strong></strong></a><strong><strong> </strong></strong>não gera apenas imagens, mas também vídeos e GIFs. Se acessarmos a API e obtivermos um vídeo ou GIF, haverá um erro e o bot não enviará a mensagem para você.</p><p>Vamos corrigir isso para que o bot envie apenas uma mensagem com um anexo de imagem. Se obtivermos um vídeo ou GIF, chamaremos a API novamente até obtermos uma imagem.</p><h4 id="1-encontre-a-correspond-ncia-da-extens-o-do-arquivo-usando-express-es-regulares"><strong><strong>1. </strong>Encontre a correspondência da extensão do arquivo usando<strong> </strong>expressões regulares</strong></h4><p>Vamos usar uma expressão regular, ou <em>regex</em>, para resolver esse problema.</p><p>Para distinguir uma imagem de um vídeo ou GIF, podemos dar uma olhada na extensão do arquivo. Precisamos somente da última parte do nosso URL.</p><pre><code>https://random.dog/*****.JPG</code></pre><p>Precisamos definir, primeiro, quais extensões de arquivo são permitidas em nosso programa.</p><pre><code>allowed_extension = ['jpg','jpeg','png']</code></pre><p>Em seguida, usamos a regex para extrair a extensão do arquivo do URL.</p><pre><code>file_extension = re.search("([^.]*)$",url).group(1).lower()</code></pre><p>Usando este código, crie uma função chamada <code>get_image_url()</code> para iterar o URL até obter a extensão de arquivo que queremos (jpg, jpeg ou png):</p><pre><code class="language-py">def get_image_url():
    allowed_extension = ['jpg','jpeg','png']
    file_extension = ''
    while file_extension not in allowed_extension:
        url = get_url()
        file_extension = re.search("([^.]*)$",url).group(1).lower()
    return url</code></pre><h4 id="2-modifique-seu-c-digo"><strong><strong>2. </strong>Modifique seu código</strong></h4><p>Ótimo! Agora, para a última parte, substitua a linha <code>url = get_url()</code> na função <code>bop()</code> por <code>url = get_image_url()</code> e seu código deve ficar assim:</p><pre><code class="language-py">from telegram.ext import Updater, InlineQueryHandler, CommandHandler
import requests
import re

def get_url():
    contents = requests.get('https://random.dog/woof.json').json()    
    url = contents['url']
    return url

def get_image_url():
    allowed_extension = ['jpg','jpeg','png']
    file_extension = ''
    while file_extension not in allowed_extension:
        url = get_url()
        file_extension = re.search("([^.]*)$",url).group(1).lower()
    return url

def bop(bot, update):
    url = get_image_url()
    chat_id = update.message.chat_id
    bot.send_photo(chat_id=chat_id, photo=url)

def main():
    updater = Updater('SEU_TOKEN')
    dp = updater.dispatcher
    dp.add_handler(CommandHandler('bop',bop))
    updater.start_polling()
    updater.idle()

if __name__ == '__main__':
    main()</code></pre><p>Legal! Tudo deve funcionar perfeitamente. Confira também a conta do GitHub do autor para obter o código.</p><p>Parabéns por terminar este tutorial. Você agora tem um bot legal para o Telegram.</p><p>Obrigado e boa sorte praticando! 😀</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
