.. _sec_linear_regression: Linear Regression ================= *Regression* refers to a set of methods for modeling the relationship between one or more independent variables and a dependent variable. In the natural sciences and social sciences, the purpose of regression is most often to *characterize* the relationship between the inputs and outputs. Machine learning, on the other hand, is most often concerned with *prediction*. Regression problems pop up whenever we want to predict a numerical value. Common examples include predicting prices (of homes, stocks, etc.), predicting length of stay (for patients in the hospital), demand forecasting (for retail sales), among countless others. Not every prediction problem is a classic regression problem. In subsequent sections, we will introduce classification problems, where the goal is to predict membership among a set of categories. Elementos Básicos de Regressão Linear ------------------------------------- *Regressão linear* pode ser a mais simples e mais popular entre as ferramentas padrão para regressão. Datado do início do século 19, A regressão linear flui a partir de algumas suposições simples. Primeiro, assumimos que a relação entre as variáveis independentes :math:`\mathbf{x}` e a variável dependente :math:`y` é linear, ou seja, esse :math:`y` pode ser expresso como uma soma ponderada dos elementos em :math:`\mathbf{x}`, dado algum ruído nas observações. Em segundo lugar, assumimos que qualquer ruído é bem comportado (seguindo uma distribuição gaussiana). Para motivar a abordagem, vamos começar com um exemplo de execução. Suponha que desejamos estimar os preços das casas (em dólares) com base em sua área (em pés quadrados) e idade (em anos). Para realmente desenvolver um modelo para prever os preços das casas, precisaríamos colocar as mãos em um conjunto de dados consistindo em vendas para as quais sabemos o preço de venda, área e idade de cada casa. Na terminologia de *machine learning*, o conjunto de dados é chamado de *dataset de treinamento* ou *conjunto de treinamento*, e cada linha (aqui os dados correspondentes a uma venda) é chamado de *exemplo* (ou *tupla*, *instância de dados*, \* amostra *). O que estamos tentando prever (preço) é chamado de* label\* (ou *rótulo*). As variáveis independentes (idade e área) em que as previsões são baseadas são chamadas de *features* (ou *covariáveis*). Normalmente, usaremos :math:`n` para denotar o número de exemplos em nosso conjunto de dados. Nós indexamos os exemplos de dados por :math:`i`, denotando cada entrada como :math:`\mathbf{x}^{(i)} = [x_1^{(i)}, x_2^{(i)}]^\top` e o *label* correspondente como :math:`y^{(i)}`. .. _subsec_linear_model: Modelo Linear ~~~~~~~~~~~~~ A suposição de linearidade apenas diz que o alvo (preço) pode ser expresso como uma soma ponderada das características (área e idade): .. math:: \mathrm{preço} = w_{\mathrm{área}}\cdot\mathrm{área} + w_{\mathrm{idade}}\cdot\mathrm{idade} + b. :label: eq_price-area In :eq:`eq_price-area`, $ w_{:raw-latex:`\mathrm{area}`}$ e :math:`w_{\mathrm{age}}` são chamados de *pesos* e :math:`b` é chamado de *bias* (também chamado de *deslocamento* ou *offset*). Os pesos determinam a influência de cada *feature* em nossa previsão e o *bias* apenas diz qual valor o preço previsto deve assumir quando todos os *features* assumem o valor 0. Mesmo que nunca vejamos nenhuma casa com área zero, ou que têm exatamente zero anos de idade, ainda precisamos do *bias* ou então vamos limitar a expressividade do nosso modelo. Estritamente falando, :eq:`eq_price-area` é uma *transformação afim* de *features* de entrada, que é caracterizada por uma *transformação linear* de *features* via soma ponderada, combinada com uma *tradução* por meio do *bias* adicionado. Dado um *dataset*, nosso objetivo é escolher os pesos :math:`\mathbf{w}` e o *bias* :math:`b` de modo que, em média, as previsões feitas de acordo com nosso modelo se ajustem o melhor possível aos preços reais observados nos dados. Modelos cuja previsão de saída é determinada pela transformação afim de *features* de entrada são *modelos lineares*, onde a transformação afim é especificada pelos pesos e *bias* escolhidos. Em disciplinas onde é comum se concentrar em conjuntos de dados com apenas alguns *features*, expressar explicitamente modelos de formato longo como esse é comum. No *machine learning*, geralmente trabalhamos com *datasets* de alta dimensão, portanto, é mais conveniente empregar a notação de álgebra linear. Quando nossas entradas consistem em :math:`d` *features*, expressamos nossa previsão :math:`\hat{y}` (em geral, o símbolo “chapéu” ou “acento circunflexo” denota estimativas) como .. math:: \hat{y} = w_1 x_1 + ... + w_d x_d + b. Coletando todas as *features* em um vetor :math:`\mathbf{x}\in\mathbb{R}^d` e todos os pesos em um vetor :math:`\mathbf{w}\in\mathbb{R}^d`, podemos expressar nosso modelo compactamente usando um produto escalar: .. math:: \hat{y} = \mathbf{w}^\top \mathbf{x} + b. :label: eq_linreg-y Em :eq:`eq_linreg-y`, o vetor :math:`\mathbf{x}` corresponde às *features* de um único exemplo de dados. Frequentemente acharemos conveniente para se referir a recursos de todo o nosso *dataset* de :math:`n` exemplos através da *matriz de design* :math:`\mathbf{X}\in\mathbb{R}^{n\times d}`. Aqui, :math:`\mathbf{X}` contém uma linha para cada exemplo e uma coluna para cada *feature*. Para uma coleção de *features* :math:`\mathbf{X}`, as previsões :math:`\hat{\mathbf{y}}\in\mathbb{R}^n` pode ser expresso por meio do produto matriz-vetor: .. math:: {\hat{\mathbf{y}}} = \mathbf{X} \mathbf{w} + b, onde a transmissão (veja :numref:`subsec_broadcasting`) é aplicada durante o somatório. Dadas as *features* de um *dataset* de treinamento :math:`\mathbf{X}` e *labels* correspondentes (conhecidos) :math:`\mathbf{y}`, o objetivo da regressão linear é encontrar o vetor de pesos :math:`\mathbf{w}` e o termo de polarização :math:`b` que dadas as *features* de um novo exemplo de dados amostrado da mesma distribuição de :math:`\mathbf{X}`, o *label* do novo exemplo será (na expectativa) previsto com o menor erro. Mesmo se acreditarmos que o melhor modelo para predizer :math:`y` dado :math:`\mathbf{x}` é linear, não esperaríamos encontrar um *dataset* do mundo real de :math:`n` exemplos onde :math:`y^{(i)}` é exatamente igual a :math:`\mathbf{w}^\top\mathbf{x}^{(i)} + b` para todos :math:`1\leq i \leq n`. Por exemplo, quaisquer instrumentos que usarmos para observar as *features* :math:`\mathbf{X}` e os *labels* :math:`\mathbf{y}` podem sofrer uma pequena quantidade de erro de medição. Assim, mesmo quando estamos confiantes que a relação subjacente é linear, vamos incorporar um termo de ruído para contabilizar esses erros. Antes de começarmos a pesquisar os melhores *parâmetros* (ou *parâmetros do modelo*) :math:`\mathbf{w}` e :math:`b`, precisaremos de mais duas coisas: (i) uma medida de qualidade para algum modelo dado; e (ii) um procedimento de atualização do modelo para melhorar sua qualidade. Função de Perda ~~~~~~~~~~~~~~~ Antes de começarmos a pensar sobre como *ajustar* os dados ao nosso modelo, precisamos determinar uma medida de *aptidão*. A *função de perda* quantifica a distância entre o valor *real* e *previsto* do *target*. A perda geralmente será um número não negativo onde valores menores são melhores e previsões perfeitas incorrem em uma perda de 0. A função de perda mais popular em problemas de regressão é o erro quadrático. Quando nossa previsão para um exemplo :math:`i` é :math:`\hat{y}^{(i)}` e o \*label verdadeiro correspondente é :math:`y^{(i)}`, o quadrado do erro é dado por: .. math:: l^{(i)}(\mathbf{w}, b) = \frac{1}{2} \left(\hat{y}^{(i)} - y^{(i)}\right)^2. A constante :math:`\frac{1}{2}` não faz diferença real mas será notacionalmente conveniente, cancelando quando tomamos a derivada da perda. Como o conjunto de dados de treinamento é fornecido a nós e, portanto, está fora de nosso controle, o erro empírico é apenas função dos parâmetros do modelo. Para tornar as coisas mais concretas, considere o exemplo abaixo onde traçamos um problema de regressão para um caso unidimensional como mostrado em :numref:`fig_fit_linreg`. .. _fig_fit_linreg: .. figure:: ../img/fit-linreg.svg Fit data with a linear model. Observe que grandes diferenças entre estimativas :math:`\hat{y}^{(i)}` e observações :math:`y^{(i)}` levam a contribuições ainda maiores para a perda, devido à dependência quadrática. Para medir a qualidade de um modelo em todo o conjunto de dados de :math:`n` exemplos, nós simplesmente calculamos a média (ou equivalentemente, somamos) as perdas no conjunto de treinamento. .. math:: L(\mathbf{w}, b) =\frac{1}{n}\sum_{i=1}^n l^{(i)}(\mathbf{w}, b) =\frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right)^2. Ao treinar o modelo, queremos encontrar os parâmetros (:math:`\mathbf{w}^*, b^*`) que minimizam a perda total em todos os exemplos de treinamento: .. math:: \mathbf{w}^*, b^* = \operatorname*{argmin}_{\mathbf{w}, b}\ L(\mathbf{w}, b). Solução Analítica ~~~~~~~~~~~~~~~~~ A regressão linear passa a ser um problema de otimização incomumente simples. Ao contrário da maioria dos outros modelos que encontraremos neste livro, a regressão linear pode ser resolvida analiticamente aplicando uma fórmula simples. Para começar, podemos incluir o *bias* :math:`b` no parâmetro :math:`\mathbf{w}` anexando uma coluna à matriz de design que consiste em todas as unidades. Então nosso problema de previsão é minimizar :math:`\|\mathbf{y} -\mathbf{X}\mathbf{w}\|^2`. Há apenas um ponto crítico na superfície de perda e corresponde ao mínimo de perda em todo o domínio. Tirando a derivada da perda em relação a :math:`\mathbf{w}` e defini-lo igual a zero produz a solução analítica (de forma fechada): .. math:: \mathbf{w}^* = (\mathbf X^\top \mathbf X)^{-1}\mathbf X^\top \mathbf{y}. Embora problemas simples como regressão linear podem admitir soluções analíticas, você não deve se acostumar com essa boa sorte. Embora as soluções analíticas permitam uma boa análise matemática, o requisito de uma solução analítica é tão restritivo que isso excluiria todo o *deep learning*. Gradiente Descendente Estocástico com *Minibatch* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mesmo nos casos em que não podemos resolver os modelos analiticamente, acontece que ainda podemos treinar modelos efetivamente na prática. Além disso, para muitas tarefas, aqueles modelos difíceis de otimizar acabam sendo muito melhores do que descobrir como treiná-los acaba valendo a pena. A principal técnica para otimizar quase qualquer modelo de *deep learning*, e que recorreremos ao longo deste livro, consiste em reduzir iterativamente o erro atualizando os parâmetros na direção que diminui gradativamente a função de perda. Este algoritmo é denominado *gradiente descendente*. A aplicação mais ingênua de gradiente descendente consiste em obter a derivada da função de perda, que é uma média das perdas calculadas em cada exemplo no *dataset*. Na prática, isso pode ser extremamente lento: devemos passar por todo o conjunto de dados antes de fazer uma única atualização. Assim, frequentemente nos contentaremos em amostrar um *minibatch* aleatório de exemplos toda vez que precisamos calcular a atualização, uma variante chamada *gradiente descendente estocástico de minibatch*. Em cada iteração, primeiro amostramos aleatoriamente um *minibatch* :math:`\mathcal{B}` consistindo em um número fixo de exemplos de treinamento. Em seguida, calculamos a derivada (gradiente) da perda média no *minibatch* em relação aos parâmetros do modelo. Finalmente, multiplicamos o gradiente por um valor positivo predeterminado :math:`\eta` e subtraimos o termo resultante dos valores dos parâmetros atuais. Podemos expressar a atualização matematicamente da seguinte forma (:math:`\partial` denota a derivada parcial): .. math:: (\mathbf{w},b) \leftarrow (\mathbf{w},b) - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{(\mathbf{w},b)} l^{(i)}(\mathbf{w},b). Para resumir, as etapas do algoritmo são as seguintes: (i) inicializamos os valores dos parâmetros do modelo, normalmente de forma aleatória; (ii) amostramos iterativamente *minibatches* aleatórios dos dados, atualizando os parâmetros na direção do gradiente negativo. Para perdas quadráticas e transformações afins, podemos escrever isso explicitamente da seguinte maneira: .. math:: \begin{aligned} \mathbf{w} &\leftarrow \mathbf{w} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{\mathbf{w}} l^{(i)}(\mathbf{w}, b) = \mathbf{w} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \mathbf{x}^{(i)} \left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right),\\ b &\leftarrow b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_b l^{(i)}(\mathbf{w}, b) = b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right). \end{aligned} :label: eq_linreg_batch_update Observe que :math:`\mathbf{w}` e :math:`\mathbf{x}` são vetores em :eq:`eq_linreg_batch_update`. Aqui, a notação vetorial mais elegante torna a matemática muito mais legível do que expressar coisas em termos de coeficientes, diga :math:`w_1, w_2, \ldots, w_d`. A cardinalidade definida :math:`|\mathcal{B}|` representa o número de exemplos em cada *minibatch* (o *tamanho do lote*) e :math:`\eta` denota a *taxa de aprendizagem*. Enfatizamos que os valores do tamanho do lote e da taxa de aprendizagem são pré-especificados manualmente e normalmente não aprendidos por meio do treinamento do modelo. Esses parâmetros são ajustáveis, mas não atualizados no loop de treinamento são chamados de *hiperparâmetros*. *Ajuste de hiperparâmetros* é o processo pelo qual os hiperparâmetros são escolhidos, e normalmente requer que os ajustemos com base nos resultados do ciclo de treinamento conforme avaliado em um *dataset de validação* separado (ou *conjunto de validação*). Após o treinamento para algum número predeterminado de iterações (ou até que algum outro critério de parada seja atendido), registramos os parâmetros estimados do modelo, denotado :math:`\hat{\mathbf{w}}, \hat{b}`. Observe que mesmo que nossa função seja verdadeiramente linear e sem ruídos, esses parâmetros não serão os minimizadores exatos da perda porque, embora o algoritmo convirja lentamente para os minimizadores, não pode alcançá-los exatamente em um número finito de etapas. A regressão linear passa a ser um problema de aprendizagem onde há apenas um mínimo em todo o domínio. No entanto, para modelos mais complicados, como redes profundas, as superfícies de perda contêm muitos mínimos. Felizmente, por razões que ainda não são totalmente compreendidas, praticantes de *deep learning* raramente se esforçam para encontrar parâmetros que minimizem a perda *em conjuntos de treinamento*. A tarefa mais formidável é encontrar parâmetros que irão atingir baixa perda de dados que não vimos antes, um desafio chamado *generalização*. Retornamos a esses tópicos ao longo do livro. Fazendo Predições com o Modelo Aprendido ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Dado o modelo de regressão linear aprendido :math:`\hat{\mathbf{w}}^\top\mathbf{x} + \hat{b}`, agora podemos estimar o preço de uma nova casa (não contido nos dados de treinamento) dada sua área :math:`x_1` e idade :math:`x_2`. Estimar *labels* dadas as características é comumente chamado de *predição* ou *inferência*. Tentaremos manter o termo *predição* porque chamando esta etapa de *inferência*, apesar de emergir como jargão padrão no *deep learning*, é um nome impróprio. Em estatísticas, *inferência* denota mais frequentemente estimar parâmetros com base em um conjunto de dados. Este uso indevido de terminologia é uma fonte comum de confusão quando os profissionais de *machine learning* conversam com os estatísticos. Vetorização para Velocidade --------------------------- Ao treinar nossos modelos, normalmente queremos processar *minibatches* inteiros de exemplos simultaneamente. Fazer isso de forma eficiente requer que nós vetorizar os cálculos e aproveitar as bibliotecas de álgebra linear rápida em vez de escrever *loops for* custosos em Python. .. raw:: html