Merge branch 'microsoft:main' into main

pull/483/head
Arianne 4 years ago committed by GitHub
commit 0425110f27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -6,7 +6,7 @@
## [Pre-lecture quiz](https://white-water-09ec41f0f.azurestaticapps.net/quiz/1/)
# Welcome
***
Welcome to this course on classical machine learning for beginners! Whether you're completely new to this topic, or an experienced ML practitioner looking to brush up on an area, we're happy to have you join us! We want to create a friendly launching spot for your ML study and would be happy to evaluate, respond to, and incorporate your [feedback](https://github.com/microsoft/ML-For-Beginners/discussions).

@ -7,13 +7,13 @@
In this lesson, we will walk through the major milestones in the history of machine learning and artificial intelligence.
The history of artificial intelligence, AI, as a field is intertwined with the history of machine learning, as the algorithms and computational advances that underpin ML fed into the development of AI. It is useful to remember that, while these fields as distinct areas of inquiry began to crystallize in the 1950s, important [algorithmical, statistical, mathematical, computational and technical discoveries](https://wikipedia.org/wiki/Timeline_of_machine_learning) predated and overlapped this era. In fact, people have been thinking about these questions for [hundreds of years](https://wikipedia.org/wiki/History_of_artificial_intelligence): this article discusses the historical intellectual underpinnings of the idea of a 'thinking machine.'
The history of artificial intelligence (AI) as a field is intertwined with the history of machine learning, as the algorithms and computational advances that underpin ML fed into the development of AI. It is useful to remember that, while these fields as distinct areas of inquiry began to crystallize in the 1950s, important [algorithmic, statistical, mathematical, computational and technical discoveries](https://wikipedia.org/wiki/Timeline_of_machine_learning) predated and overlapped this era. In fact, people have been thinking about these questions for [hundreds of years](https://wikipedia.org/wiki/History_of_artificial_intelligence): this article discusses the historical intellectual underpinnings of the idea of a 'thinking machine.'
## Notable discoveries
- 1763, 1812 [Bayes Theorem](https://wikipedia.org/wiki/Bayes%27_theorem) and its predecessors. This theorem and its applications underlie inference, describing the probability of an event occurring based on prior knowledge.
- 1805 [Least Square Theory](https://wikipedia.org/wiki/Least_squares) by French mathematician Adrien-Marie Legendre. This theory, which you will learn about in our Regression unit, helps in data fitting.
- 1913 [Markov Chains](https://wikipedia.org/wiki/Markov_chain) named after Russian mathematician Andrey Markov is used to describe a sequence of possible events based on a previous state.
- 1913 [Markov Chains](https://wikipedia.org/wiki/Markov_chain), named after Russian mathematician Andrey Markov, is used to describe a sequence of possible events based on a previous state.
- 1957 [Perceptron](https://wikipedia.org/wiki/Perceptron) is a type of linear classifier invented by American psychologist Frank Rosenblatt that underlies advances in deep learning.
- 1967 [Nearest Neighbor](https://wikipedia.org/wiki/Nearest_neighbor) is an algorithm originally designed to map routes. In an ML context it is used to detect patterns.
- 1970 [Backpropagation](https://wikipedia.org/wiki/Backpropagation) is used to train [feedforward neural networks](https://wikipedia.org/wiki/Feedforward_neural_network).
@ -89,7 +89,7 @@ This epoch saw a new era for ML and AI to be able to solve some of the problems
## Now
Today, machine learning and AI touch almost every part of our lives. This era calls for careful understanding of the risks and potentials effects of these algorithms on human lives. As Microsoft's Brad Smith has stated, "Information technology raises issues that go to the heart of fundamental human-rights protections like privacy and freedom of expression. These issues heighten responsibility for tech companies that create these products. In our view, they also call for thoughtful government regulation and for the development of norms around acceptable uses" ([source](https://www.technologyreview.com/2019/12/18/102365/the-future-of-ais-impact-on-society/)).
Today machine learning and AI touch almost every part of our lives. This era calls for careful understanding of the risks and potentials effects of these algorithms on human lives. As Microsoft's Brad Smith has stated, "Information technology raises issues that go to the heart of fundamental human-rights protections like privacy and freedom of expression. These issues heighten responsibility for tech companies that create these products. In our view, they also call for thoughtful government regulation and for the development of norms around acceptable uses" ([source](https://www.technologyreview.com/2019/12/18/102365/the-future-of-ais-impact-on-society/)).
It remains to be seen what the future holds, but it is important to understand these computer systems and the software and algorithms that they run. We hope that this curriculum will help you to gain a better understanding so that you can decide for yourself.

@ -0,0 +1,214 @@
# Começar com Python e Scikit-learn para modelos de regressão
![Resumo das regressões numa nota de esboço
](../../../sketchnotes/ml-regression.png)
> Sketchnote by [Tomomi Imura](https://www.twitter.com/girlie_mac)
## [Questionário pré-palestra](https://white-water-09ec41f0f.azurestaticapps.net/quiz/9/)
> ### [Esta lição está disponível em R!](./solution/R/lesson_1-R.ipynb)
## Introdução
Nestas quatro lições, você vai descobrir como construir modelos de regressão. Discutiremos para que são em breve. Mas antes de fazer qualquer coisa, certifique-se de ter as ferramentas certas para iniciar o processo!
Nesta lição, aprenderá a:
- Configurar o seu computador para tarefas locais de aprendizagem automática.
- Trabalhe com cadernos Jupyter.
- Utilize scikit-learn, incluindo a instalação.
- Explore a regressão linear com um exercício prático.
## Instalações e configurações
[![Configurar Python com código de estúdio visual
](https://img.youtube.com/vi/yyQM70vi7V8/0.jpg)](https://youtu.be/yyQM70vi7V8 "Configurar Python com código de estúdio visual
")
> 🎥 Clique na imagem acima para um vídeo: utilizando Python dentro do Código VS.
1. **Instalar Python**. Certifique-se de que [Python](https://www.python.org/downloads/) está instalado no seu computador. Você usará Python para muitas tarefas de ciência de dados e machine learning. A maioria dos sistemas informáticos já inclui uma instalação Python. Há úteis [Python Pacotes de codificação](https://code.visualstudio.com/learn/educators/installers?WT.mc_id=academic-15963-cxa) disponível também, para facilitar a configuração para alguns utilizadores.
Alguns usos de Python, no entanto, requerem uma versão do software, enquanto outros requerem uma versão diferente. Por esta razão, é útil trabalhar dentro de um [ambiente virtual](https://docs.python.org/3/library/venv.html).
2. **Instalar código de estúdio visual**. Certifique-se de que tem o Código do Estúdio Visual instalado no seu computador. Siga estas instruções para
[instalar Código do Estúdio Visual](https://code.visualstudio.com/) para a instalação básica. Você vai usar Python em Código estúdio visual neste curso, então você pode querer relembrá-lo [configurar código de estúdio visual](https://docs.microsoft.com/learn/modules/python-install-vscode?WT.mc_id=academic-15963-cxa) para o desenvolvimento de Python.
> Fique confortável com python trabalhando através desta coleção de [Aprender módulos](https://docs.microsoft.com/users/jenlooper-2911/collections/mp1pagggd5qrq7?WT.mc_id=academic-15963-cxa)
3. **Instale Scikit-learn**, seguindo [estas instruções]
(https://scikit-learn.org/stable/install.html). Uma vez que precisa de garantir que utiliza o Python 3, recomenda-se que utilize um ambiente virtual. Note que se estiver a instalar esta biblioteca num Mac M1, existem instruções especiais na página acima ligada.
1. **Instale o Caderno Jupyter**. Você precisará [instalar o pacote Jupyter](https://pypi.org/project/jupyter/).
## O seu ambiente de autoria ML
Você vai usar **cadernos** para desenvolver o seu código Python e criar modelos de aprendizagem automática. Este tipo de ficheiro é uma ferramenta comum para cientistas de dados, e podem ser identificados pelo seu sufixo ou extensão `.ipynb`.
Os cadernos são um ambiente interativo que permite ao desenvolvedor codificar e adicionar notas e escrever documentação em torno do código que é bastante útil para projetos experimentais ou orientados para a investigação.
## Exercício - trabalhe com um caderno
Nesta pasta, encontrará o ficheiro _notebook.ipynb_.
1. Abra _notebook.ipynb_ em Código de Estúdio Visual.
Um servidor Jupyter começará com o Python 3+ iniciado. Encontrará áreas do caderno que podem ser `executadas`, peças de código. Pode executar um bloco de código, selecionando o ícone que parece um botão de reprodução.
2. Selecione o ícone `md` e adicione um pouco de marcação, e o seguinte texto **# Bem-vindo ao seu caderno**.
Em seguida, adicione um pouco de código Python.
5. Escreva **print ('olá caderno')** no bloco de código.
6. Selecione a seta para executar o código.
Deve ver a declaração impressa:
```saída
Olá caderno
```
![Código VS com um caderno aberto](../images/notebook.jpg)
Pode interligar o seu código com comentários para auto-documentar o caderno.
✅ Pense por um minuto como o ambiente de trabalho de um web developer é diferente do de um cientista de dados.
## Em funcionamento com Scikit-learn
Agora que python está montado no seu ambiente local, e você está confortável com os cadernos jupyter, vamos ficar igualmente confortáveis com Scikit-learn (pronunciá-lo 'sci' como em 'ciência'). Scikit-learn fornece uma [API extensiva](https://scikit-learn.org/stable/modules/classes.html#api-ref) para ajudá-lo a executar tarefas ML.
De acordo com o seu [site](https://scikit-learn.org/stable/getting_started.html), "O Scikit-learn é uma biblioteca de aprendizagem automática de código aberto que suporta a aprendizagem supervisionada e sem supervisão. Também fornece várias ferramentas para a montagem de modelos, pré-processamento de dados, seleção e avaliação de modelos, e muitas outras utilidades."
Neste curso, você usará scikit-learn e outras ferramentas para construir modelos de machine learning para executar o que chamamos de tarefas tradicionais de aprendizagem automática. Evitámos deliberadamente redes neurais e aprendizagem profunda, uma vez que estão melhor cobertas no nosso próximo currículo de IA para principiantes.
O scikit-learn torna simples construir modelos e avaliá-los para uso. Está focado principalmente na utilização de dados numéricos e contém vários conjuntos de dados prontos para uso como ferramentas de aprendizagem. Também inclui modelos pré-construídos para os alunos experimentarem. Vamos explorar o processo de carregamento de dados pré-embalados e usar um modelo ml incorporado no estimador com o Scikit-learn com alguns dados básicos.
## Exercício - o seu primeiro caderno Scikit-learn
> Este tutorial foi inspirado no exemplo [de regressão linear](https://scikit-learn.org/stable/auto_examples/linear_model/plot_ols.html#sphx-glr-auto-examples-linear-model-plot-ols-py) no site da Scikit-learn.
No ficheiro _notebook.ipynb_ associado a esta lição, limpe todas as células premindo o ícone 'caixote do lixo'.
Nesta secção, você vai trabalhar com um pequeno conjunto de dados sobre diabetes que é incorporado em Scikit-learn para fins de aprendizagem. Imagine que queria testar um tratamento para pacientes diabéticos. Os modelos de Machine Learning podem ajudá-lo a determinar quais os pacientes que responderiam melhor ao tratamento, com base em combinações de variáveis. Mesmo um modelo de regressão muito básico, quando visualizado, pode mostrar informações sobre variáveis que o ajudariam a organizar os seus ensaios clínicos teóricos.
✅ There are many types of regression methods, and which one you pick depends on the answer you're looking for. If you want to predict the probable height for a person of a given age, you'd use linear regression, as you're seeking a **numeric value**. If you're interested in discovering whether a type of cuisine should be considered vegan or not, you're looking for a **category assignment** so you would use logistic regression. You'll learn more about logistic regression later. Think a bit about some questions you can ask of data, and which of these methods would be more appropriate.
Vamos começar com esta tarefa.
### Bibliotecas de importação
Para esta tarefa importaremos algumas bibliotecas:
- **matplotlib**. É uma ferramenta útil [de grafimento](https://matplotlib.org/) e vamos usá-lo para criar um enredo de linha.
- **numpy**. [numpy](https://numpy.org/doc/stable/user/whatisnumpy.html) é uma biblioteca útil para o tratamento de dados numéricos em Python.
- **sklearn**. Este é o [Scikit-learn](https://scikit-learn.org/stable/user_guide.html) biblioteca.
Importe algumas bibliotecas para ajudar nas suas tarefas.
1. Adicione as importações digitando o seguinte código:
```python
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, model_selection
```
Acima está a importar `matplottlib`, `numpy` e está a importar `datasets`, `linear_model` e `model_selection` de `sklearn`. É utilizado `model_selection` para dividir dados em conjuntos de treino e teste.
## O conjunto de dados da diabetes
O conjunto de dados incorporado [diabetes](https://scikit-learn.org/stable/datasets/toy_dataset.html#diabetes-dataset) Inclui 442 amostras de dados em torno da diabetes, com 10 variáveis de características, algumas das quais incluem:
- idade: idade em anos
- bmi: índice de massa corporal
- bp: pressão arterial média
- s1 tc: T-Cells (um tipo de glóbulos brancos)
✅ Este conjunto de dados inclui o conceito de 'sexo' como uma variável de característica importante para a investigação em torno da diabetes. Muitos conjuntos de dados médicos incluem este tipo de classificação binária. Pense um pouco sobre como categorizações como esta podem excluir certas partes de uma população de tratamentos.
Agora, carregue os dados X e Y.
> 🎓 Lembre-se, isto é aprendizagem supervisionada, e precisamos de um alvo chamado "y".
Numa nova célula de código, carregue o conjunto de dados da diabetes chamando `load_diabetes()` A entrada `return_X_y=True` indica que `X` será uma matriz de dados, e `y` será o alvo de regressão.
1. Adicione alguns comandos de impressão para mostrar a forma da matriz de dados e o seu primeiro elemento:
```python
X, y = datasets.load_diabetes(return_X_y=True)
print(X.shape)
print(X[0])
```
O que estás a receber como resposta, é um tuple. O que está a fazer é atribuir os dois primeiros valores da tuple para `X` and `y` respectivamente. Saiba mais [sobre tuples](https://wikipedia.org/wiki/Tuple).
Pode ver que estes dados têm 442 itens moldados em matrizes de 10 elementos:
```text
(442, 10)
[ 0.03807591 0.05068012 0.06169621 0.02187235 -0.0442235 -0.03482076
-0.04340085 -0.00259226 0.01990842 -0.01764613]
```
✅ Pense um pouco sobre a relação entre os dados e o alvo de regressão. A regressão linear prevê relações entre a característica X e a variável alvo. Pode encontrar o [alvo](https://scikit-learn.org/stable/datasets/toy_dataset.html#diabetes-dataset) para o conjunto de dados da diabetes na documentação? O que é que este conjunto de dados está a demonstrar, tendo em conta esse objetivo?
2. Em seguida, selecione uma parte deste conjunto de dados para traçar, organizando-o numa nova matriz usando a função `newaxis` da Numpy. Vamos usar a regressão linear para gerar uma linha entre valores nestes dados, de acordo com um padrão que determina.
```python
X = X[:, np.newaxis, 2]
```
✅ A qualquer momento, imprima os dados para verificar a sua forma.
3. Agora que tem dados prontos a serem traçados, pode ver se uma máquina pode ajudar a determinar uma divisão lógica entre os números deste conjunto de dados. Para isso, é necessário dividir os dados (X) e o alvo (y) em conjuntos de teste e treino. O Scikit-learn tem uma forma simples de o fazer; pode dividir os seus dados de teste num dado momento.
```python
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.33)
```
4. Agora está pronto para treinar o seu modelo! Carregue o modelo linear de regressão e treine-o com os seus conjuntos de treinamento X e y usando `modelo.fit()`:
```python
model = linear_model.LinearRegression()
model.fit(X_train, y_train)
```
`modelo.fit()` é uma função que você verá em muitas bibliotecas ML, como TensorFlow
5. Em seguida, crie uma previsão utilizando dados de teste, utilizando a função `predict()`. Isto será usado para traçar a linha entre grupos de dados
```python
y_pred = model.predict(X_test)
```
6. Agora é hora de mostrar os dados num enredo. Matplotlib é uma ferramenta muito útil para esta tarefa. Crie uma dispersão de todos os dados de teste X e y, e use a previsão para traçar uma linha no local mais apropriado, entre os agrupamentos de dados do modelo.
```python
plt.scatter(X_test, y_test, color='black')
plt.plot(X_test, y_pred, color='blue', linewidth=3)
plt.xlabel('Scaled BMIs')
plt.ylabel('Disease Progression')
plt.title('A Graph Plot Showing Diabetes Progression Against BMI')
plt.show()
```
![a scatterplot showing datapoints around diabetes](../images/scatterplot.png)
✅ Pense um pouco sobre o que está acontecendo aqui. Uma linha reta está a passar por muitos pequenos pontos de dados, mas o que está a fazer exatamente? Consegue ver como deve ser capaz de usar esta linha para prever onde um novo ponto de dados invisível se deve encaixar em relação ao eixo y do enredo? Tente colocar em palavras o uso prático deste modelo.
Parabéns, construíste o teu primeiro modelo linear de regressão, criaste uma previsão com ele, e exibiste-o num enredo!
---
## 🚀Challenge
Defina uma variável diferente deste conjunto de dados. Dica: edite esta linha:`X = X[:, np.newaxis, 2]`. Tendo em conta o objetivo deste conjunto de dados, o que é que consegue descobrir sobre a progressão da diabetes como uma doença?
## [Questionário pós-palestra](https://white-water-09ec41f0f.azurestaticapps.net/quiz/10/)
## Review & Self Study
Neste tutorial, trabalhou com uma simples regressão linear, em vez de univariado ou regressão linear múltipla. Leia um pouco sobre as diferenças entre estes métodos, ou dê uma olhada[este vídeo](https://www.coursera.org/lecture/quantifying-relationships-regression-models/linear-vs-nonlinear-categorical-variables-ai2Ef)
Leia mais sobre o conceito de regressão e pense sobre que tipo de perguntas podem ser respondidas por esta técnica. Tome este [tutorial](https://docs.microsoft.com/learn/modules/train-evaluate-regression-models?WT.mc_id=academic-15963-cxa) para aprofundar a sua compreensão.
## Missão
[Um conjunto de dados diferente](assignment.md)

@ -0,0 +1,13 @@
# Regressão com Scikit-learn
## Instruções
Dê uma olhada no conjunto de [dados Linnerud](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_linnerud.html#sklearn.datasets.load_linnerud) em Scikit-learn. Este conjunto de dados tem vários [alvos](https://scikit-learn.org/stable/datasets/toy_dataset.html#linnerrud-dataset): 'Consiste em três variáveis de exercício (dados) e três variáveis fisiológicas (alvo) recolhidas de vinte homens de meia-idade num clube de fitness'
Nas suas próprias palavras, descreva como criar um modelo de Regressão que traçaria a relação entre a cintura e quantos situps são realizados. Faça o mesmo para os outros pontos de dados neste conjunto de dados.
## Rubrica
| Critérios | exemplares | Adequado | Necessidades de Melhoria |
| ------------------------------ | ----------------------------------- | ----------------------------- | -------------------------- |
| Enviar um parágrafo descritivo | Parágrafo bem escrito é submetido | Algumas frases são submetidas | Nenhuma descrição é fornecida |

@ -0,0 +1,207 @@
# Crie um modelo de regressão usando o Scikit-learn: preparar e visualizar dados
![Infográfico de visualização de dados](../images/data-visualization.png)
Infographic by [Dasani Madipalli](https://twitter.com/dasani_decoded)
## [Teste de pré-aula](https://white-water-09ec41f0f.azurestaticapps.net/quiz/11/)
> ### [Esta lição está disponível em R!](./solution/R/lesson_2-R.ipynb)
## Introdução
Agora que você está configurado com as ferramentas necessárias para começar a lidar com a construção de modelos de aprendizagem automática com o Scikit-learn, você está pronto para começar a fazer perguntas sobre seus dados. Como você trabalha com dados e aplica soluções ML, é muito importante entender como fazer a pergunta certa para desbloquear adequadamente os potenciais de seu conjunto de dados.
Nesta lição, você aprenderá:
- Como preparar seus dados para a criação de modelos.
- Como usar Matplotlib para visualização de dados.
[![Preparação e Visualização de Dados](https://img.youtube.com/vi/11AnOn_OAcE/0.jpg)](https://youtu.be/11AnOn_OAcE "Preparando e Visualizando vídeo de dados - Clique para Assistir!")
> 🎥 Clique na imagem acima para ver um vídeo que aborda os principais aspectos desta lição
## Fazendo a pergunta certa sobre seus dados
A pergunta que você precisa responder determinará que tipo de algoritmos de ML você utilizará. E a qualidade da resposta que você recebe de volta será fortemente dependente da natureza de seus dados.
Dê uma olhada nos [dados](../data/US-pumpkins.csv) fornecidos para esta lição. Você pode abrir este arquivo .csv no Código VS. Um skim rápido imediatamente mostra que há espaços em branco e uma mistura de strings e dados numéricos. Há também uma coluna estranha chamada 'Package' onde os dados são uma mistura entre 'sacks', 'bins' e outros valores. Os dados, de fato, são um pouco confusos.
Na verdade, não é muito comum ser dotado de um conjunto de dados que está completamente pronto para usar para criar um modelo ML pronto para uso. Nesta lição, você aprenderá como preparar um conjunto de dados bruto usando bibliotecas Python padrão. Você também aprenderá várias técnicas para visualizar os dados.
## Estudo de caso: "mercado da abóbora"
Nesta pasta você encontrará um arquivo .csv na pasta raiz `data` chamada [US-pumpkins.csv](../data/US-pumpkins.csv) que inclui 1757 linhas de dados sobre o mercado de abóboras, classificadas em agrupamentos por cidade. Estes são dados brutos extraídos dos [Specialty Crops Terminal Markets Standard Reports](https://www.marketnews.usda.gov/mnp/fv-report-config-step1?type=termPrice) distribuídos pelo Departamento de Agricultura dos Estados Unidos.
### Preparando dados
Estes dados são do domínio público. Ele pode ser baixado em muitos arquivos separados, por cidade, a partir do site USDA. Para evitar muitos arquivos separados, nós concatenamos todos os dados da cidade em uma planilha, assim nós já _preparamos_ os dados um pouco. A seguir, vamos dar uma olhada nos dados.
### Os dados da abóbora - primeiras conclusões
O que você nota sobre esses dados? Vocês já viram que há uma mistura de strings, números, espaços em branco e valores estranhos que você precisa entender.
Que pergunta você pode fazer sobre esses dados, usando uma técnica de Regressão? E quanto a "Prever o preço de uma abóbora à venda durante um determinado mês". Observando novamente os dados, há algumas alterações que você precisa fazer para criar a estrutura de dados necessária para a tarefa.
## Exercício - analisar os dados da abóbora
Vamos usar [Pandas](https://pandas.pydata.org/), (o nome significa `Python Data Analysis`) uma ferramenta muito útil para moldar dados, para analisar e preparar esses dados de abóbora.
### Primeiro, verifique se há datas ausentes
Primeiro, você precisará seguir as etapas para verificar se há datas ausentes:
1. Converta as datas em um formato de mês (essas são datas americanas, portanto o formato é `MM/DD/AAAA`).
2. Extraia o mês para uma nova coluna.
Abra o arquivo _notebook.ipynb_ no Visual Studio Code e importe a planilha para um novo quadro de dados do Pandas.
1. Use a função `head()` para exibir as cinco primeiras linhas.
```python
import pandas as pd
pumpkins = pd.read_csv('../data/US-pumpkins.csv')
pumpkins.head()
```
Qual função você usaria para exibir as últimas cinco linhas?
1. Verifique se há dados ausentes no banco de dados atual:
```python
pumpkins.isnull().sum()
```
Faltam dados, mas talvez não seja importante para a tarefa em questão.
1. Para facilitar o trabalho com seu banco de dados, solte várias de suas colunas, usando `drop()`, mantendo apenas as colunas necessárias:
```python
new_columns = ['Package', 'Month', 'Low Price', 'High Price', 'Date']
pumpkins = pumpkins.drop([c for c in pumpkins.columns if c not in new_columns], axis=1)
```
### Segundo, determinar o preço médio da abóbora
Pense sobre como determinar o preço médio de uma abóbora em um determinado mês. Que colunas você escolheria para esta tarefa? Dica: você precisará de 3 colunas.
Solução: utilize a média das colunas `Preço Baixo` e Preço Alto` para preencher a nova coluna Preço e converta a coluna Data para mostrar apenas o mês. Felizmente, de acordo com a verificação acima, não há dados ausentes para datas ou preços.
1. Para calcular a média, adicione o seguinte código:
2.
```python
price = (pumpkins['Low Price'] + pumpkins['High Price']) / 2
month = pd.DatetimeIndex(pumpkins['Date']).month
```
✅Sinta-se à vontade para imprimir quaisquer dados que você gostaria de verificar usando `print(month)`.
3. Agora, copie seus dados convertidos em um novo dataframe Pandas:
```python
new_pumpkins = pd.DataFrame({'Month': month, 'Package': pumpkins['Package'], 'Low Price': pumpkins['Low Price'],'High Price': pumpkins['High Price'], 'Price': price})
```
A impressão do seu dataframe mostrará um conjunto de dados limpo e organizado no qual você pode construir seu novo modelo de regressão.
### Mas espere! Há algo estranho aqui
Se você observar a coluna `Package`, as abóboras são vendidas em várias configurações diferentes. Algumas são vendidas em medidas de "1 1/9 bushel", e algumas em medidas de "1/2 bushel", algumas por abóbora, algumas por libra, e algumas em caixas grandes com larguras variadas.
> Abóboras parecem muito difíceis de pesar consistentemente
Analisando os dados originais, é interessante que qualquer coisa com `Unidade de Venda` igual a 'CADA' ou 'POR CAIXA' também tenha o tipo `Pacote` por polegada, por caixa ou 'cada'. As abóboras parecem ser muito difíceis de pesar consistentemente, então vamos filtrá-las selecionando apenas as abóboras com a cadeia "bushel" na coluna `Pacote`.
1. Adicione um filtro na parte superior do arquivo, sob a importação .csv inicial:
```python
pumpkins = pumpkins[pumpkins['Package'].str.contains('bushel', case=True, regex=True)]
```
Se você imprimir os dados agora, você pode ver que você está apenas recebendo as 415 ou mais linhas de dados contendo abóboras pelo bushel.
### Mas espere! Há mais uma coisa a fazer
Você notou que o montante de bushel varia por linha? Você precisa normalizar o preço para que você mostre o preço por bushel, então faça algumas contas para padronizá-lo.
1. Adicione estas linhas após o bloco criar o dataframe new_pumpkins:
```python
new_pumpkins.loc[new_pumpkins['Package'].str.contains('1 1/9'), 'Price'] = price/(1 + 1/9)
new_pumpkins.loc[new_pumpkins['Package'].str.contains('1/2'), 'Price'] = price/(1/2)
```
✅ De acordo com [O Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308), o peso de um bushel depende do tipo de produto, pois é uma medida de volume. "Um bushel de tomates, por exemplo, deve pesar 56 libras... Folhas e verdes ocupam mais espaço com menos peso, então um alqueire de espinafre pesa apenas 20 libras." É tudo muito complicado! Não nos preocupemos em fazer uma conversão bushel-to-pound, e em vez disso o preço pelo bushel. Todo este estudo de bushels de abóboras, no entanto, vai para mostrar como é muito importante entender a natureza dos seus dados!
Agora, você pode analisar o preço por unidade com base em sua medição de bushel. Se você imprimir os dados mais uma vez, poderá ver como eles são padronizados.
Você notou que as abóboras vendidas pela metade do bushel são muito caras? Você pode descobrir por quê? Dica: abóboras pequenas são muito mais caras do que as grandes, provavelmente porque há muito mais delas por bushel, dado o espaço não utilizado tomado por uma grande abóbora de torta oca.
## Estratégias de visualização
Parte do papel do cientista de dados é demonstrar a qualidade e a natureza dos dados com os quais eles estão trabalhando. Para fazer isso, muitas vezes criam visualizações interessantes, ou gráficos, gráficos e gráficos, mostrando diferentes aspectos dos dados. Dessa forma, eles são capazes de mostrar visualmente relacionamentos e lacunas que de outra forma são difíceis de descobrir.
Visualizações também podem ajudar a determinar a técnica de aprendizado de máquina mais apropriada para os dados. Um gráfico de dispersão que parece seguir uma linha, por exemplo, indica que os dados são um bom candidato para um exercício de regressão linear.
Uma biblioteca de visualização de dados que funciona bem em notebooks Jupyter é [Matplotlib](https://matplotlib.org/) (que você também viu na lição anterior).
> Obtenha mais experiência com visualização de dados em [estes tutoriais](https://docs.microsoft.com/learn/modules/explore-analyze-data-with-python?WT.mc_id=university-15963-cxa).
## Exercício - experimente com Matplotlib
Tente criar alguns gráficos básicos para exibir o novo banco de dados que você acabou de criar. O que um gráfico de linha básica mostraria?
1. Importar Matplotlib no topo do arquivo, sob a importação Pandas:
```python
import matplotlib.pyplot as plt
```
1. Execute novamente todo o bloco de anotações para atualizar.
1. Na parte inferior do notebook, adicione uma célula para plotar os dados como uma caixa:
```python
price = new_pumpkins.Price
month = new_pumpkins.Month
plt.scatter(price, month)
plt.show()
```
![Uma distribuição que mostra a relação preço/mês](../images/scatterplot.png)
Será isto um enredo útil? Alguma coisa sobre isso o surpreende?
Não é particularmente útil, uma vez que tudo o que apresenta nos seus dados como uma distribuição de pontos num determinado mês.
### Tornar útil
Para que os gráficos apresentem dados úteis, normalmente é necessário agrupar os dados de alguma forma. Vamos tentar criar um desenho onde o eixo Y mostre os meses e os dados demonstram a distribuição de dados.
1. Adicionar uma célula para criar um gráfico de barras agrupado:
```python
new_pumpkins.groupby(['Month'])['Price'].mean().plot(kind='bar')
plt.ylabel("Pumpkin Price")
```
![Um gráfico de barras que mostra a relação preço/mês](../images/barchart.png)
Esta é uma visualização de dados mais útil! Parece indicar que o preço mais alto para as abrigas ocorre em setembro e outubro. Isso atende às suas expetativas? Porque ou porque não?
## 🚀 desafio
Explore os diferentes tipos de visualização que o Matplotlib oferece. Que tipos são mais apropriados para problemas de regressão?
## [Questionário pós-palestra](https://white-water-09ec41f0f.azurestaticapps.net/quiz/12/)
## Revisão e Estudo Automático
Dê uma vista de olhos às muitas formas de visualizar dados. Disponibilize uma lista das várias bibliotecas e anote quais as melhores para determinados tipos de tarefas, por exemplo, visualizações 2D vs. visualizações 3D. O que você descobre?
## Atribuição
[A explorar visualização](assignment.md)

@ -0,0 +1,9 @@
# Exploração de Visualizações
Existem várias bibliotecas diferentes que estão disponíveis para visualização de dados. Crie algumas visualizações utilizando os dados da Abóbora nesta lição com matplotlib e nascidos num caderno de amostras. Com que bibliotecas é mais fácil de trabalhar?
## Rubrica
Critérios | exemplares | Adequado | Necessidades de Melhoria |
| -------- | --------- | -------- | ----------------- |
| | Um caderno é submetido com duas explorações/visualizações| Um caderno é submetido com uma exploração/visualizações | Um caderno não é submetido |

@ -0,0 +1,332 @@
# Crie um modelo de regressão utilizando o Scikit-learning: regressão de dois modos
![Regressão linear vs polinomial infográfica](./images/linear-polynomial.png)
> Infográfico de [Dasani Madipalli](https://twitter.com/dasani_decoded)
## [Questionário pré-seleção](https://white-water-09ec41f0f.azurestaticapps.net/quiz/13/)
> ### [Esta lição está disponível em R!](./solution/R/lesson_3-R.ipynb)
### Introdução
Até agora, vocês exploraram o que é a regressão com os dados de exemplo recolhidos a partir do conjunto de dados de preços da abóbora que vamos usar ao longo desta lição. Também o visualizaram utilizando Matplotlib.
Agora está preparado para mergulhar mais profundamente na regressão para o ML. Nesta lição, você vai aprender mais sobre dois tipos de regressão: _regressão linear básica_ e _regressão polinomial_, juntamente com alguma da matemática subjacente a estas técnicas.
> Ao longo deste currículo, assumimos um conhecimento mínimo de matemática, e procuramos torná-lo acessível a estudantes provenientes de outras áreas, por isso, procuremos notas, notas de 🧮, diagramas e outras ferramentas de aprendizagem para ajudar na compreensão.
### Pré-requisitos
Já devem conhecer a estrutura dos dados relativos à abóbora que estamos a analisar. Pode encontrá-lo pré-carregado e previamente limpo no ficheiro _notebook.ipynb_ desta lição. No ficheiro, o preço da abóbora é apresentado por defeito num novo dataframe. Certifique-se de que pode executar estes blocos de notas em kernels no Código do Visual Studio.
### Preparação
Como lembrete, está a carregar estes dados para fazer perguntas sobre os mesmos.
- Quando é o melhor momento para comprar abóboras?
- Que preço posso esperar de um caso de abóbora miniatura?
- Devo comprá-los em cestos de meia-bushel ou pela caixa de bushel 1 1/9?
Vamos continuar a investigar estes dados.
Na lição anterior, você criou um dataframe Pandas e o preencheu com parte do conjunto de dados original, padronizando os preços pelo bushel. Ao fazer isso, no entanto, você só conseguiu reunir cerca de 400 datapops e apenas nos meses de outono.
Dê uma vista de olhos aos dados que pré-carregámos no bloco de notas que acompanha esta lição. Os dados são pré-carregados e um gráfico de dispersão inicial é desenhado para mostrar os dados do mês. Talvez possamos obter um pouco mais de detalhe sobre a natureza dos dados limpando-os mais.
## Uma linha de regressão linear
Como aprenderam na lição 1, o objetivo de um exercício de regressão linear é conseguir desenhar uma linha para:
- **Mostrar relações de variáveis***. Mostrar a relação entre variáveis
- **Faça previsões**. Faça previsões precisas sobre onde um novo ponto de dados cairia em relação a essa linha.
É típico de **Regressão dos Quadrados Menos** desenhar este tipo de linha. O termo 'menos quadrados' significa que todos os pontos de dados em torno da linha de regressão são são quadrados e depois adicionados. Idealmente, essa soma final é o mais pequena possível, porque queremos um número reduzido de erros, ou `menos quadrados` .
Fazemo-lo porque queremos modelar uma linha que tenha a menor distância cumulativa de todos os nossos pontos de dados. Nós também fazemos o quadrado dos termos antes de os adicionarmos, uma vez que estamos preocupados com a sua magnitude e não com a sua direção.
> ** 🧮 Mostrar a matemática**
>
> Esta linha, denominada a _linha de best fit_, pode ser expressa por [uma equação](https://en.wikipedia.org/wiki/Simple_linear_regression):
>
> ```
> Y = a + bX
> ```
>
> `X` é a "variável explicativa". `Y` é a 'variável dependente'. O declive da linha é `b` e `a` é a interceção y, que se refere ao valor de `Y` quando `X = 0`.
>
>![calcule o declive](images/slope.png)
>
> Primeiro, calcular o declive `b`. Infográfico por [Jen Looper](https://twitter.com/jenlooper)
>
> Por outras palavras, e referindo-se à pergunta original dos nossos dados de abóbora: "prever o preço de uma abóbora por bordel por mês", `X` referiria-se ao preço e `Y` referiria-se ao mês de venda.
>
>![complete a equação](images/calculation.png)
>
> Calcular o valor de Y. Se você está pagando por volta de $4, deve ser abril! Infográfico por [Jen Looper](https://twitter.com/jenlooper)
>
> A matemática que calcula a linha deve demonstrar o declive da linha, que também depende da interceção, ou onde `Y` está situado quando `X = 0`.
>
> Pode observar o método de cálculo destes valores no Web site [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html). Visite também [esta calculadora de Menos quadrados](https://www.mathsisfun.com/data/least-squares-calculator.html) para ver como os valores dos números têm impacto na linha.
## Correlação
Mais um termo a compreender é o **Coeficiente de Correlação** entre as variáveis X e Y fornecidas. Usando um gráfico de dispersão, você pode visualizar rapidamente este coeficiente. Um desenho com pontos de dados dispersos numa linha reta tem uma correlação elevada, mas um desenho com pontos de dados dispersos por todo o lado entre X e Y tem uma correlação baixa.
Um bom modelo de regressão linear será aquele que tem um Coeficiente de Correlação elevado (mais perto de 1 que 0) utilizando o método de Regressão dos Menos Quadrados com uma linha de regressão.
✅ Executar o bloco de notas que acompanha esta lição e olhar para o gráfico de distribuição City to Price. Os dados que associam a cidade ao preço das vendas de abóbora parecem ter uma correlação alta ou baixa, de acordo com a sua interpretação visual da distribuição?
## Preparar os dados para regressão
Agora que têm uma compreensão da matemática por detrás deste exercício, criem um modelo de Regressão para ver se conseguem prever que pacote de abóbora terá os melhores preços de abóbora. Alguém que adquira abóbora para uma correção de abóbora de férias poderá querer que esta informação seja capaz de otimizar as suas compras de pacotes de abóbora para a correção.
Já que você vai usar o Scikit-learning, não há razão para fazer isso à mão (embora você pudesse!). No bloco principal de processamento de dados do bloco de notas de lição, adicione uma biblioteca do Scikit-learning para converter automaticamente todos os dados de cadeia em números:
```python
from sklearn.preprocessing import LabelEncoder
new_pumpkins.iloc[:, 0:-1] = new_pumpkins.iloc[:, 0:-1].apply(LabelEncoder().fit_transform)
```
Se olharem para o dataframe new_bompkins, veem que todas as cadeias são agora numéricas. Isto torna mais difícil para você ler, mas muito mais inteligível para o Scikit - aprender!
Agora, pode tomar decisões mais educadas (não apenas com base no aparecimento de um gráfico de dispersão) sobre os dados que melhor se adequam à regressão.
Tente encontrar uma boa correlação entre dois pontos dos seus dados para criar, potencialmente, um bom modelo preditivo. Acontece que há apenas uma correlação fraca entre a Cidade e o Preço:
```python
print(new_pumpkins['City'].corr(new_pumpkins['Price']))
0.32363971816089226
```
No entanto, há uma correlação um pouco melhor entre o Pacote e o seu Preço. Isso faz sentido, certo? Normalmente, quanto maior for a caixa de produção, maior será o preço.
```python
print(new_pumpkins['Package'].corr(new_pumpkins['Price']))
0.6061712937226021
```
Uma boa pergunta a fazer sobre estes dados será: 'Que preço posso esperar de um determinado pacote de abóbora?'
Vamos construir este modelo de regressão
## A criar um modelo linear
Antes de criar o seu modelo, faça mais uma arrumação dos seus dados. Remova todos os dados nulos e verifique novamente como são os dados.
```python
new_pumpkins.dropna(inplace=True)
new_pumpkins.info()
```
Em seguida, crie um novo dataframe a partir deste conjunto mínimo e imprima-o:
```python
new_columns = ['Package', 'Price']
lin_pumpkins = new_pumpkins.drop([c for c in new_pumpkins.columns if c not in new_columns], axis='columns')
lin_pumpkins
```
```output
Package Price
70 0 13.636364
71 0 16.363636
72 0 16.363636
73 0 15.454545
74 0 13.636364
... ... ...
1738 2 30.000000
1739 2 28.750000
1740 2 25.750000
1741 2 24.000000
1742 2 24.000000
415 rows × 2 columns
```
1. Agora, pode atribuir os seus dados de coordenadas X e y:
```python
X = lin_pumpkins.values[:, :1]
y = lin_pumpkins.values[:, 1:2]
```
✅ O que está acontecendo aqui? Está a utilizar [Python slice notation](https://stackoverflow.com/questions/509211/understanding-slice-notation/509295#509295) para criar matrizes para povoar X e y.
2. Em seguida, inicie as rotinas de construção de modelos de regressão:
```python
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)
pred = lin_reg.predict(X_test)
accuracy_score = lin_reg.score(X_train,y_train)
print('Model Accuracy: ', accuracy_score)
```
Porque a correlação não é particularmente boa, o modelo produzido não é terrivelmente preciso.
```output
Model Accuracy: 0.3315342327998987
```
3. Pode visualizar a linha desenhada no processo:
```python
plt.scatter(X_test, y_test, color='black')
plt.plot(X_test, pred, color='blue', linewidth=3)
plt.xlabel('Package')
plt.ylabel('Price')
plt.show()
```
![Um gráfico de dispersão que mostra a relação preço/pacote](./images/linear.png)
4. Teste o modelo contra uma variedade hipotética:
```python
lin_reg.predict( np.array([ [2.75] ]) )
```
O preço devolvido por esta Variedades mitológicas é:
```output
array([[33.15655975]])
```
Esse número faz sentido, se a lógica da linha de regressão se mantiver verdadeira.
🎃 Parabéns, criaram um modelo que pode ajudar a prever o preço de algumas variedades de abóbora. A sua mancha de abóbora de férias será bonita. Mas é provável que se possa criar um modelo melhor!
## Regressão polinomial
Outro tipo de regressão linear é a regressão polinomial. Embora por vezes haja uma relação linear entre variáveis - quanto maior é o volume da abóbora, maior é o preço - por vezes estas relações não podem ser desenhadas como um plano ou uma linha reta.
✅ Aqui estão [mais alguns exemplos](https://online.stat.psu.edu/stat501/lesson/9/9.8) de dados que podem utilizar regressão polinomial
Vejam outra vez a relação entre Varity e Price no desenho anterior. Parece que este gráfico de dispersão deve ser necessariamente analisado por uma linha reta? Talvez não. Neste caso, pode-se tentar uma regressão polinomial.
✅ Polinomiais são expressões matemáticas que podem ser compostas por uma ou mais variáveis e coeficientes
A regressão polinomial cria uma linha curvada para ajustar melhor os dados não lineares.
1. Vamos recriar um dataframe povoado com um segmento dos dados originais da abóbora:
```python
new_columns = ['Variety', 'Package', 'City', 'Month', 'Price']
poly_pumpkins = new_pumpkins.drop([c for c in new_pumpkins.columns if c not in new_columns], axis='columns')
poly_pumpkins
```
Uma boa maneira de visualizar as correlações entre os dados nos dataframes é exibi-los em um gráfico 'colorido':
2. Utilize o método `Background_gradient()` com o valor de argumento `colarm`:
```python
corr = poly_pumpkins.corr()
corr.style.background_gradient(cmap='coolwarm')
```
Este código cria um mapa de calor:
![Um mapa de calor que mostra a correlação de dados](./images/heatmap.png)
Olhando para este gráfico, pode visualizar a boa correlação entre Pacote e Preço. Portanto, deveriam ser capazes de criar um modelo um pouco melhor do que o último.
### Criar um pipeline
Scikit-learning inclui uma API útil para a construção de modelos de regressão polinomial - o `make_pipeline` [API](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.make_pipeline.html?highlight=pipeline#sklearn.pipeline.make_pipeline). É criado um "pipeline" que é uma cadeia de estimadores. Neste caso, o pipeline inclui funcionalidades polinomiais ou previsões que formam um caminho não linear.
1. Criar as colunas X e y:
```python
X=poly_pumpkins.iloc[:,3:4].values
y=poly_pumpkins.iloc[:,4:5].values
```
2. Crie o pipeline chamando o método "make_pipeline()":
```python
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
pipeline = make_pipeline(PolynomialFeatures(4), LinearRegression())
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
pipeline.fit(np.array(X_train), y_train)
y_pred=pipeline.predict(X_test)
```
### Criar uma sequência
Neste ponto, é necessário criar um novo dataframe com dados _sorted_ para que o pipeline possa criar uma sequência.
Adicionar o seguinte código:
```python
df = pd.DataFrame({'x': X_test[:,0], 'y': y_pred[:,0]})
df.sort_values(by='x',inplace = True)
points = pd.DataFrame(df).to_numpy()
plt.plot(points[:, 0], points[:, 1],color="blue", linewidth=3)
plt.xlabel('Package')
plt.ylabel('Price')
plt.scatter(X,y, color="black")
plt.show()
```
Criou um novo dataframe chamando `pd.DataFrame`. Em seguida, ordenou os valores chamando `sort_values()`. Finalmente criou um desenho polinomial:
![Um desenho polinomial que mostra a relação pacote/preço](./images/polynomial.png)
Pode ver uma linha curvada que se adapta melhor aos seus dados.
Vamos verificar a precisão do modelo:
```python
accuracy_score = pipeline.score(X_train,y_train)
print('Model Accuracy: ', accuracy_score)
```
E voilá!
```output
Model Accuracy: 0.8537946517073784
```
Isso é melhor! Tente prever um preço:
### Efetuar uma previsão
Podemos introduzir um novo valor e obter uma previsão?
Chame `predict()` para fazer uma previsão:
```python
pipeline.predict( np.array([ [2.75] ]) )
```
É-lhe dada esta previsão:
```output
array([[46.34509342]])
```
Faz sentido, dado o enredo! E, se este é um modelo melhor do que o anterior, olhando para os mesmos dados, é preciso orçar para estas abrigas mais caras!
🏆 Parabéns! Criaram dois modelos de regressão numa lição. Na última secção sobre regressão, irá obter informações sobre regressão logística para determinar categorias.
## 🚀 desafio
Teste várias variáveis diferentes neste bloco de notas para ver como a correlação corresponde à precisão do modelo.
##[Questionário pós-palestra](https://white-water-09ec41f0f.azurestaticapps.net/quiz/14/)
## Revisão e Estudo Automático
Nesta lição, aprendemos sobre a Regressão Linear. Há outros tipos importantes de Regressão. Leia sobre as técnicas Stepwise, Ridge, Lasso e Elasticnet. Um bom curso para estudar para aprender mais é o [curso de Aprendizagem Estatística de Stanford](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning)
## Atribuição
[Criar um Modelo](assignment.md)

@ -0,0 +1,11 @@
# Criar um modelo de regressão
## Instruções
Nesta lição foi-lhe mostrado como construir um modelo usando a Regressão Linear e Polinomial. Utilizando este conhecimento, encontre um conjunto de dados ou use um dos conjuntos incorporados da Scikit-learn para construir um novo modelo. Explique no seu caderno porque escolheu a técnica que escolheu e demonstre a precisão do seu modelo. Se não for preciso, explique porquê.
## Rubrica
| Critérios | exemplares | Adequado | Necessidades de Melhoria |
| -------- | ------------------------------------------------------------ | -------------------------- | ------------------------------- |
| | apresenta um caderno completo com uma solução bem documentada | a solução está incompleta| a solução é imperfeita ou buggy |

@ -0,0 +1,302 @@
# Regressão logística para prever categorias
![Infográfico logístico vs. regressão linear](../images/logistic-linear.png)
> Infographic by [Dasani Madipalli](https://twitter.com/dasani_decoded)
## [Questionário pré-palestra](https://white-water-09ec41f0f.azurestaticapps.net/quiz/15/)
> ### [Esta lição está disponível em R!](./solution/R/lesson_4-R.ipynb)
## Introdução
Nesta lição final sobre Regressão, uma das técnicas básicas _classic_ ML, vamos dar uma olhada na Regressão Logística. Usaria esta técnica para descobrir padrões para prever categorias binárias. Isto é chocolate doce ou não? Esta doença é contagiosa ou não? Este cliente escolherá este produto ou não?
Nesta lição, aprenderá:
- Uma nova biblioteca para visualização de dados
- Técnicas de regressão logística
✅ aprofundar a sua compreensão de trabalhar com este tipo de regressão neste [módulo Aprender](https://docs.microsoft.com/learn/modules/train-evaluate-classification-models?WT.mc_id=academic-15963-cxa)
## Pré-requisito
Tendo trabalhado com os dados da abóbora, estamos agora familiarizados o suficiente para perceber que há uma categoria binária com a qual podemos trabalhar:` Cor`.
Vamos construir um modelo de regressão logística para prever que, dadas algumas variáveis, _what cor de uma dada abóbora é provável que be_ (🎃 laranja ou 👻 branco).
> Porque estamos a falar de classificação binária num agrupamento de aulas sobre regressão? Apenas para conveniência linguística, uma vez que a regressão logística é [realmente um método de classificação](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression),embora um linear baseado. Saiba mais sobre outras formas de classificar os dados no próximo grupo de aulas.
## Definir a pergunta
Para os nossos propósitos, vamos expressar isto como um binário: "Laranja" ou "Não Laranja". Existe também uma categoria de "listrado" no nosso conjunto de dados, mas há poucos casos dele, pelo que não a utilizaremos. Desaparece assim que removemos os valores nulos do conjunto de dados, de qualquer forma.
> 🎃 facto divertido, às vezes chamamos abóboras brancas de abóboras "fantasma". Não são muito fáceis de esculpir, por isso não são tão populares como os laranjas, mas são fixes!
## About logistic regression
A regressão logística difere da regressão linear, que aprendeu anteriormente, de algumas formas importantes.
### Classificação binária
A regressão logística não oferece as mesmas características que a regressão linear. O primeiro oferece uma previsão sobre uma categoria binária ("laranja ou não laranja"),) enquanto esta é capaz de prever valores contínuos, por exemplo dada a origem de uma abóbora e a hora da colheita, _how muito o seu preço irá rise_.
![Modelo de classificação de abóbora](../images/pumpkin-classifier.png)
> Infographic by [Dasani Madipalli](https://twitter.com/dasani_decoded)
### Outras classificações
Existem outros tipos de regressão logística, incluindo multinóia e ordinária:
- **Multinomial**, que envolve ter mais de uma categoria - "Laranja, Branco e Listrado".
- **Ordinal**, que envolve categorias ordenadas, úteis se quiséssemos encomendar os nossos resultados logicamente, como as nossas abóboras que são encomendadas por um número finito de tamanhos (mini,sm,med,lg,xl,xxl).
![Regressão multinomial vs ordinal](../images/multinomial-ordinal.png)
> Infographic by [Dasani Madipalli](https://twitter.com/dasani_decoded)
### Ainda é linear
Embora este tipo de Regressão seja tudo sobre "previsões de categoria", ainda funciona melhor quando há uma relação linear clara entre a variável dependente (cor) e as outras variáveis independentes (o resto do conjunto de dados, como o nome e o tamanho da cidade). É bom ter uma ideia de se há alguma linearidade dividindo estas variáveis ou não.
### Variáveis NÃO têm que correlacionar
Lembras-te de como a regressão linear funcionou melhor com variáveis mais correlacionadas? A regressão logística é o oposto - as variáveis não têm que se alinhar. Isso funciona para estes dados que têm correlações um pouco fracas.
### Precisa de muitos dados limpos
A regressão logística dará resultados mais precisos se utilizar mais dados; nosso pequeno conjunto de dados não é o ideal para esta tarefa, por isso tenha isso em mente.
✅ Pense nos tipos de dados que se emprestariam bem à regressão logística
## Exercício - arrumar os dados
Primeiro, limpe um pouco os dados, baixando os valores nulos e selecionando apenas algumas das colunas:
1. Adicione o seguinte código:
```python
from sklearn.preprocessing import LabelEncoder
new_columns = ['Color','Origin','Item Size','Variety','City Name','Package']
new_pumpkins = pumpkins.drop([c for c in pumpkins.columns if c not in new_columns], axis=1)
new_pumpkins.dropna(inplace=True)
new_pumpkins = new_pumpkins.apply(LabelEncoder().fit_transform)
```
Pode sempre dar uma olhada no seu novo dataframe:
```python
new_pumpkins.info
```
### Visualização - grelha lado a lado
Por esta altura já já carregou o [caderno de entrada](./notebook.ipynb) com dados de abóbora mais uma vez e limpou-os de modo a preservar um conjunto de dados contendo algumas variáveis, incluindo `Color`. Vamos visualizar o quadro de dados no caderno usando uma biblioteca diferente: [Seaborn](https://seaborn.pydata.org/index.html), que é construída em Matplotlib que usamos anteriormente.
Seaborn oferece algumas maneiras limpas de visualizar os seus dados. Por exemplo, pode comparar distribuições dos dados por cada ponto numa grelha lado a lado.
1. Crie tal rede através da instantânea `PairGrid`, utilizando os nossos dados de abóbora `new_pumpkins`, seguidos de `map()`:
```python
import seaborn as sns
g = sns.PairGrid(new_pumpkins)
g.map(sns.scatterplot)
```
![A grid of visualized data](../images/grid.png)
Ao observar dados lado a lado, pode ver como os dados de Cor se relacionam com as outras colunas.
✅ Dada esta grelha de dispersão, quais são algumas explorações interessantes que podes imaginar?
### Use um enredo de enxame
Uma vez que a Cor é uma categoria binária (Laranja ou Não), chama-se "dados categóricos" e precisa de "uma abordagem mais [especializada](https://seaborn.pydata.org/tutorial/categorical.html?highlight=bar) à visualização". Há outras formas de visualizar a relação desta categoria com outras variáveis.
Você pode visualizar variáveis lado a lado com parcelas seaborn.
1. Experimente um plano de 'enxame' para mostrar a distribuição de valores:
```python
sns.swarmplot(x="Color", y="Item Size", data=new_pumpkins)
```
![Um enxame de dados visualizados](../images/swarm.png)
### Enredo de violino
Um gráfico de tipo 'violino' é útil, pois você pode visualizar facilmente a forma como os dados nas duas categorias são distribuídos. Os gráficos de violino não funcionam tão bem com conjuntos de dados menores, pois a distribuição é exibida mais 'suavemente'.
1. Como parâmetros `x=Color`, `kind="violin"` e chamada `catplot()`:
```python
sns.catplot(x="Color", y="Item Size",
kind="violin", data=new_pumpkins)
```
![a violin type chart](images/violin.png)
✅ Tente criar este enredo, e outros enredos de Seaborn, usando outras variáveis.
Agora que temos uma ideia da relação entre as categorias binárias de cor e o grupo maior de tamanhos, vamos explorar a regressão logística para determinar a cor provável de uma dada abóbora.
> **🧮 Mostre-Me A Matemática**
>
> Lembram-se como a regressão linear frequentemente usava mínimos quadrados ordinários para chegar a um valor? A regressão logística baseia-se no conceito de "máxima verossimilhança" utilizando [funções sigmoides](https://wikipedia.org/wiki/Sigmoid_function). Uma 'Função Sigmoide' em uma trama se parece com uma forma 'S'. Ele pega um valor e o mapeia para algum lugar entre 0 e 1. Sua curva também é chamada de "curva logística". Sua fórmula é assim:
>
> ![função logística](images/sigmoid.png)
>
> onde o ponto médio do sigmoide se encontra no ponto 0 de x, L é o valor máximo da curva, e k é a inclinação da curva. Se o resultado da função for maior que 0,5, o rótulo em questão receberá a classe '1' da escolha binária. Caso contrário, será classificado como "0".
## Crie o seu modelo
Construir um modelo para encontrar essas classificações binárias é surpreendentemente simples no Scikit-learn.
1. Selecione as variáveis que deseja utilizar no seu modelo de classificação e divida os conjuntos de treino e teste que chamam `train_test_split()`:
```python
from sklearn.model_selection import train_test_split
Selected_features = ['Origin','Item Size','Variety','City Name','Package']
X = new_pumpkins[Selected_features]
y = new_pumpkins['Color']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
```
1. Agora você pode treinar seu modelo, chamando `fit()` com seus dados de treinamento e imprimir o resultado:
```python
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(classification_report(y_test, predictions))
print('Predicted labels: ', predictions)
print('Accuracy: ', accuracy_score(y_test, predictions))
```
Dê uma olhada no placar do seu modelo. Não é tão ruim, considerando que você tem apenas cerca de 1000 linhas de dados:
```output
precision recall f1-score support
0 0.85 0.95 0.90 166
1 0.38 0.15 0.22 33
accuracy 0.82 199
macro avg 0.62 0.55 0.56 199
weighted avg 0.77 0.82 0.78 199
Predicted labels: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 1 0 0 1 0 0 0 1 0]
```
## Melhor compreensão através de uma matriz de confusão
Enquanto você pode obter um relatório de placar [termos](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html?highlight=classification_report#sklearn.metrics.classification_report) imprimindo os itens acima, você pode ser capaz de entender seu modelo mais facilmente usando uma [matriz confusão](https://scikit-learn.org/stable/modules/model_evaluation.html#confusion-matrix) para nos ajudar a entender como o modelo está se saindo.
> 🎓 A '[matriz de confusão](https://wikipedia.org/wiki/Confusion_matrix)' (ou 'matriz de erros') é uma tabela que expressa os verdadeiros versus falsos positivos e negativos do seu modelo, avaliando assim a precisão das previsões.
1. Para usar uma métrica de confusão, chame`confusion_matrix()`:
```python
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, predictions)
```
Dê uma olhada na matriz de confusão do seu modelo:
```output
array([[162, 4],
[ 33, 0]])
```
No Scikit-learn, matrizes de confusão Linhas (eixo 0) são rótulos reais e colunas (eixo 1) são rótulos previstos.
| | 0 | 1 |
| :---: | :---: | :---: |
| 0 | TN | FP |
| 1 | FN | TP |
O que está acontecendo aqui? Digamos que nosso modelo é solicitado a classificar abóboras entre duas categorias binárias, categoria 'laranja' e categoria 'não-laranja'.
- Se o seu modelo prevê uma abóbora como não laranja e pertence à categoria 'não-laranja' na realidade chamamos-lhe um verdadeiro negativo, mostrado pelo número superior esquerdo.
- Se o seu modelo prevê uma abóbora como laranja e pertence à categoria 'não-laranja' na realidade chamamos-lhe um falso negativo, mostrado pelo número inferior esquerdo.
- Se o seu modelo prevê uma abóbora como não laranja e pertence à categoria 'laranja' na realidade chamamos-lhe um falso positivo, mostrado pelo número superior direito.
- Se o seu modelo prevê uma abóbora como laranja e ela pertence à categoria 'laranja' na realidade nós chamamos de um verdadeiro positivo, mostrado pelo número inferior direito.
Como vocês devem ter adivinhado, é preferível ter um número maior de verdadeiros positivos e verdadeiros negativos e um número menor de falsos positivos e falsos negativos, o que implica que o modelo tem melhor desempenho.
Como a matriz de confusão se relaciona com precisão e evocação? Lembre-se, o relatório de classificação impresso acima mostrou precisão (0,83) e recuperação (0,98).
Precision = tp / (tp + fp) = 162 / (162 + 33) = 0.8307692307692308
Recall = tp / (tp + fn) = 162 / (162 + 4) = 0.9759036144578314
✅ Q: De acordo com a matriz de confusão, como foi o modelo? A: Nada mal. há um bom número de verdadeiros negativos, mas também vários falsos negativos.
Vamos revisitar os termos que vimos anteriormente com a ajuda do mapeamento da matriz confusão de TP/TN e FP/FN:
🎓 precisão: TP/(TP + FP) A fração de instâncias relevantes entre as instâncias recuperadas (por exemplo, quais rótulos estavam bem rotulados)
🎓 Chamada: TP/(TP + FN) A fração de instâncias relevantes que foram recuperadas, sejam bem rotuladas ou não
🎓 f1- score: (2 * precisão * recolha)/(precisão + recolha) Uma média ponderada da precisão e recolha, sendo a melhor 1 e a pior 0
Suporte 🎓: O número de ocorrências de cada rótulo recuperado
🎓 precisão: (TP + TN)/(TP + TN + FP + FN) A percentagem de rótulos previstos com precisão para uma amostra.
🎓 Méd. de Macro: O cálculo das métricas médias não ponderadas para cada rótulo, sem levar em conta o desequilíbrio do rótulo.
🎓 Média Ponderada: O cálculo das métricas médias para cada label, levando em conta o desequilíbrio de label ponderando-as pelo suporte (o número de instâncias verdadeiras para cada label).
Consegue pensar qual métrica deve observar se quiser que o seu modelo reduza o número de falsos negativos?
## Visualizar a curva de ROC deste modelo
Este não é um mau modelo; sua precisão está na faixa de 80%, então idealmente você poderia usá-lo para prever a cor de uma abóbora dado um conjunto de variáveis.
Vamos fazer mais uma visualização para ver a chamada pontuação 'ROC':
```python
from sklearn.metrics import roc_curve, roc_auc_score
y_scores = model.predict_proba(X_test)
# calculate ROC curve
fpr, tpr, thresholds = roc_curve(y_test, y_scores[:,1])
sns.lineplot([0, 1], [0, 1])
sns.lineplot(fpr, tpr)
```
Usando Seaborn novamente, plote a [Característica de operação de recepção](https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html?highlight=roc) ou ROC do modelo. Curvas ROC são frequentemente usadas para obter uma visão da saída de um classificador em termos de seus verdadeiros versus falsos positivos. "As curvas ROC geralmente apresentam taxa positiva verdadeira no eixo Y e taxa positiva falsa no eixo X." Assim, a inclinação da curva e o espaço entre a linha do ponto médio e a matéria da curva: você quer uma curva que rapidamente se encaminha para cima e sobre a linha. No nosso caso, há falsos positivos para começar, e então a linha se encaminha para cima e para cima corretamente:
![ROC](./images/ROC.png)
Finalmente, use o Scikit-learn [`roc_auc_score` API](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html?highlight=roc_auc#sklearn.metrics.roc_auc_score) para calcular a 'Área sob a curva' (AUC) real:
```python
auc = roc_auc_score(y_test,y_scores[:,1])
print(auc)
```
O resultado é `0,6976998904709748`. Dado que a AUC varia de 0 a 1, você quer uma grande pontuação, uma vez que um modelo que é 100% correto em suas previsões terá uma AUC de 1; nesse caso, o modelo é _muito bom_.
Em lições futuras sobre classificações, você aprenderá a iterar para melhorar as pontuações do seu modelo. Mas por enquanto, parabéns! Você completou essas lições de regressão!
---
## 🚀Desafio
Há muito mais a desempacotar em relação à regressão logística! Mas a melhor maneira de aprender é experimentar. Encontre um conjunto de dados que se preste a esse tipo de análise e construa um modelo com ele. O que você aprende? dica: tente [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) para obter conjuntos de dados interessantes.
## [Teste pós-aula](https://white-water-09ec41f0f.azurestaticapps.net/quiz/16/)
## Análise e autoestudo
Leia as primeiras páginas de [este artigo de Stanford](https://web.stanford.edu/~jurafsky/slp3/5.pdf) sobre alguns usos práticos para regressão logística. Pense em tarefas que são mais adequadas para um ou outro tipo de tarefas de regressão que estudamos até agora. O que funcionaria melhor?
## Atribuição
[Repetindo esta regressão](assignment.md)

@ -0,0 +1,11 @@
## Retrying alguma regressão
## Instruções
Na lição, usaste um subconjunto dos dados da abóbora. Agora, volte aos dados originais e tente usá-lo todo, limpo e padronizado, para construir uma Regressão Logística model.
## Rubrica
| Critérios | exemplares | Adequado | Necessidades de Melhoria |
| -------- | ----------------------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------- |
| | Um caderno é apresentado com um modelo bem explicado e bem-adundo | Um caderno é apresentado com um modelo que funciona minimamente | Um caderno é apresentado com um modelo de sub-desempenho ou nenhum|

@ -13,7 +13,7 @@ In North America, pumpkins are often carved into scary faces for Halloween. Let'
The lessons in this section cover types of regression in the context of machine learning. Regression models can help determine the _relationship_ between variables. This type of model can predict values such as length, temperature, or age, thus uncovering relationships between variables as it analyzes data points.
In this series of lessons, you'll discover the difference between linear vs. logistic regression, and when you should use one or the other.
In this series of lessons, you'll discover the differences between linear and logistic regression, and when you should prefer one over the other.
In this group of lessons, you will get set up to begin machine learning tasks, including configuring Visual Studio Code to manage notebooks, the common environment for data scientists. You will discover Scikit-learn, a library for machine learning, and you will build your first models, focusing on Regression models in this chapter.

@ -0,0 +1,38 @@
# Modelos de regressão para aprendizagem automática
## Tópico regional: Modelos de regressão para preços de abóbora na América do Norte 🎃
Na América do Norte, as abóboras são muitas vezes esculpidas em rostos assustadores para o Halloween. Vamos descobrir mais sobre estes fascinantes vegetais!
![jack-o-lanterns](./images/jack-o-lanterns.jpg)
> Photo by <a href="https://unsplash.com/@teutschmann?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Beth Teutschmann</a> on <a href="https://unsplash.com/s/photos/jack-o-lanterns?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## O que vai aprender
[![Introduction to Regression](https://img.youtube.com/vi/5QnJtDad4iQ/0.jpg)](https://youtu.be/5QnJtDad4iQ "Regressão Vídeo de introdução - Clique para ver
!")
> 🎥 Clique na imagem acima para obter um vídeo de introdução rápida a esta lição
As lições nesta secção abrangem tipos de regressão no contexto da aprendizagem automática. Os modelos de regressão podem ajudar a determinar a _relação_ entre variáveis. Este tipo de modelo pode prever valores como comprimento, temperatura ou idade, descobrindo assim relações entre variáveis à medida que analisa pontos de dados.
Nesta série de lições, você vai descobrir a diferença entre regressão logística linear vs. e quando você deve usar uma ou outra.
Neste grupo de lições, você será configurado para iniciar tarefas de machine learning, incluindo configurar o Código do Estúdio Visual para gerir cadernos, o ambiente comum para cientistas de dados. Você vai descobrir Scikit-learn, uma biblioteca para machine learning, e você vai construir seus primeiros modelos, focando-se em modelos de Regressão neste capítulo.
> Existem ferramentas de baixo código úteis que podem ajudá-lo a aprender sobre trabalhar com modelos de regressão. Tente
[Azure ML for this task](https://docs.microsoft.com/learn/modules/create-regression-model-azure-machine-learning-designer/?WT.mc_id=academic-15963-cxa)
### Lessons
1. [Ferramentas do comércio](1-Tools/README.md)
2. [Gestão de dados](2-Data/README.md)
3. [Linear and polynomial regression](3-Linear/README.md)
4. [Logistic regression](4-Logistic/README.md)
---
### Credits
"ML com regressão" foi escrito com ♥️ por[Jen Looper](https://twitter.com/jenlooper)
♥️ Os colaboradores do quiz incluem:[Muhammad Sakib Khan Inan](https://twitter.com/Sakibinan) e [Ornella Altunyan](https://twitter.com/ornelladotcom)
O conjunto de dados de abóbora é sugerido por [este projeto em Kaggle](https://www.kaggle.com/usda/a-year-of-pumpkin-prices) e os seus dados são obtidos a partir do [Relatórios padrão dos mercados de terminais de culturas especiais](https://www.marketnews.usda.gov/mnp/fv-report-config-step1?type=termPrice) distribuído pelo Departamento de Agricultura dos Estados Unidos. Adicionámos alguns pontos em torno da cor com base na variedade para normalizar a distribuição. Estes dados estão no domínio público.

@ -0,0 +1,347 @@
# Criar um Aplicativo Web para usar um Modelo ML
Nesta lição, você treinará um modelo ML em um conjunto de dados que está fora deste mundo: _Avistamentos de OVNIs no último século_, provenientes do banco de dados do NUFORC.
Você aprenderá:
- Como "picles" um modelo treinado
- Como usar esse modelo em um aplicativo Flask
Continuaremos a usar notebooks para limpar dados e treinar nosso modelo, mas você pode levar o processo um passo adiante explorando o uso de um modelo "selvagem", por assim dizer: em um aplicativo Web.
Para fazer isso, você precisa construir um aplicativo Web usando Flask.
## [Teste de pré-aula](https://white-water-09ec41f0f.azurestaticapps.net/quiz/17/)
## Criando um aplicativo
Há várias maneiras de criar aplicativos Web para consumir modelos de aprendizado de máquina. Sua arquitetura da Web pode influenciar a maneira como seu modelo é treinado. Imagine que você está trabalhando em um negócio onde o grupo de ciência de dados treinou um modelo que eles querem que você use em um aplicativo.
### Considerações
Há muitas perguntas que você precisa fazer:
- **É um aplicativo Web ou um aplicativo móvel?** Se você estiver criando um aplicativo móvel ou precisar usar o modelo em um contexto de IoT, poderá usar [TensorFlow Lite](https://www.tensorflow.org/lite/) e usar o modelo em um aplicativo Android ou iOS.
- **Onde o modelo residirá?** Na nuvem ou localmente?
- **Suporte off-line.** O aplicativo precisa trabalhar off-line?
- **Que tecnologia foi usada para treinar o modelo?** A tecnologia escolhida pode influenciar as ferramentas que você precisa usar.
- **Usando fluxo de Tensor.** Se você estiver treinando um modelo usando TensorFlow, por exemplo, esse ecossistema oferece a capacidade de converter um modelo TensorFlow para uso em um aplicativo Web usando [TensorFlow.js](https://www.tensorflow.org/js/).
- **Usando o PyTorch.** Se você estiver criando um modelo usando uma biblioteca como [PyTorch](https://pytorch.org/), terá a opção de exportá-lo no formato [ONNX](https://onnx.ai/) (Open Neural Network Exchange) para uso em aplicativos Web JavaScript que podem usar o [Onnx Runtime](https://www.onnxruntime.ai/). Essa opção será explorada em uma lição futura para um modelo treinado com o Scikit.
- **Usando o Lobe.ai ou o Azure Custom Vision.** Se você estiver usando um sistema ML SaaS (Software as a Service) como [Lobe.ai](https://lobe.ai/) ou [Azure Custom Vision](https://azure.microsoft.com/services/cognitive-services/custom-vision-service/?WT.mc_id=academy-15963-cxa) para treinar um modelo, esse tipo de software fornece maneiras de exportar o modelo para várias plataformas, incluindo a criação de uma API sob medida ser consultado na nuvem pelo aplicativo online.
Você também tem a oportunidade de construir um aplicativo web Flask inteiro que seria capaz de treinar o próprio modelo em um navegador da web. Isso também pode ser feito usando TensorFlow.js em um contexto JavaScript.
Para nossos propósitos, já que estamos trabalhando com notebooks baseados em Python, vamos explorar as etapas que você precisa seguir para exportar um modelo treinado de tal notebook para um formato legível por um aplicativo web construído em Python.
## Ferramenta
Para esta tarefa, você precisa de duas ferramentas: Flask e Pickle, ambos em Python.
O que é [Frasco](https://palletsprojects.com/p/flask/)? Definido como um 'microframework' por seus criadores, o Flask fornece as características básicas de frameworks web usando Python e um motor de modelagem para construir páginas web. Dê uma olhada em [este módulo de aprendizado](https://docs.microsoft.com/learn/modules/python-flask-build-ai-web-app?WT.mc_id=academic-15963-cxa) para praticar a construção com o Flask.
✅ O que é [Pickle](https://docs.python.org/3/library/pickle.html)? Pickle 🥒 é um módulo Python que serializa e desserializa uma estrutura de objeto Python. Ao "pichar" um modelo, você serializa ou achata sua estrutura para uso na web. Tenha cuidado: o pickle não é intrinsecamente seguro, portanto, tenha cuidado se for solicitado a `cancelar o pickle` de um arquivo. Um arquivo em conserto tem o sufixo `.pkl`.
## Exercício - limpar seus dados
Nesta lição, você usará dados de 80.000 avistamentos de UFO, coletados pelo [NUFORC](https://nuforc.org) (Centro Nacional de Relatórios de UFO). Estes dados têm algumas descrições interessantes de avistamentos de UFO, por exemplo:
- **Descrição de exemplo longo.** "Um homem emerge de um feixe de luz que brilha em um campo gramado à noite e corre em direção ao estacionamento da Texas Instruments".
- **Breve descrição do exemplo.** "as luzes nos perseguiram".
A planilha [ufos.csv](./data/ufos.csv) inclui colunas sobre `city`, `state` e `country` onde ocorreu o avistamento, `shape` do objeto e sua `latitude` e `longitude`.
No espaço em branco [notebook](notebook.ipynb) incluído nesta lição:
1. importe `pandas`, `matplotlib` e `numpy` como fez nas lições anteriores e importe a planilha ufos. Você pode dar uma olhada em um conjunto de dados de amostra:
```python
import pandas as pd
import numpy as np
ufos = pd.read_csv('./data/ufos.csv')
ufos.head()
```
1.Converta os dados ufos em um pequeno dataframe com títulos novos. Verifique os valores exclusivos no campo `País`.
```python
ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']})
ufos.Country.unique()
```
1. Agora, você pode reduzir a quantidade de dados que precisamos lidar, eliminando quaisquer valores nulos e importando apenas avistamentos entre 1-60 segundos:
```python
ufos.dropna(inplace=True)
ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)]
ufos.info()
```
1. Importe a biblioteca 'LabelEncoder' do Scikit-learn para converter os valores de texto dos países em um número:
✅ LabelEncoder codifica os dados em ordem alfabética
```python
from sklearn.preprocessing import LabelEncoder
ufos['Country'] = LabelEncoder().fit_transform(ufos['Country'])
ufos.head()
```
Seus dados devem ter esta aparência:
```output
Seconds Country Latitude Longitude
2 20.0 3 53.200000 -2.916667
3 20.0 4 28.978333 -96.645833
14 30.0 4 35.823889 -80.253611
23 60.0 4 45.582778 -122.352222
24 3.0 3 51.783333 -0.783333
```
## Exercício - construa seu modelo
Agora você pode se preparar para treinar um modelo dividindo os dados no grupo de treinamento e teste.
1. Selecione os três recursos que você deseja treinar como seu vetor X, e o vetor y será o `País`. Você quer digitar `Segundos`, `Latitude` e `Longitude` e obter um ID de país para retornar.
```python
from sklearn.model_selection import train_test_split
Selected_features = ['Seconds','Latitude','Longitude']
X = ufos[Selected_features]
y = ufos['Country']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
```
1. Treine seu modelo usando regressão logística:
```python
from sklearn.metrics import accuracy_score, classification_report
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(classification_report(y_test, predictions))
print('Predicted labels: ', predictions)
print('Accuracy: ', accuracy_score(y_test, predictions))
```
A precisão não é ruim **(cerca de 95%)**, sem surpresas, já que `País` e `Latitude/Longitude` se correlacionam.
O modelo que você criou não é muito revolucionário, pois você deve ser capaz de inferir um `País` a partir de sua `Latitude` e `Longitude`, mas é um bom exercício para tentar treinar a partir de dados brutos que você limpou, exportou e, em seguida, usar esse modelo em um aplicativo Web.
## Exercício - 'pickle' seu modelo
Agora, é hora de _pickle_ seu modelo! Você pode fazer isso em algumas linhas de código. Uma vez que seja _pickled_, carregue seu modelo em pickles e teste-o em uma matriz de dados de amostra contendo valores para segundos, latitude e longitude,
```python
import pickle
model_filename = 'ufo-model.pkl'
pickle.dump(model, open(model_filename,'wb'))
model = pickle.load(open('ufo-model.pkl','rb'))
print(model.predict([[50,44,-12]]))
```
O modelo retorna **'3'**, que é o código de país do Reino Unido. Selvagem! 👽
## Exercício - criar um aplicativo Flask
Agora você pode construir um aplicativo Flask para chamar seu modelo e retornar resultados semelhantes, mas de uma forma mais visualmente agradável.
1. Comece criando uma pasta chamada **web-app** ao lado do arquivo _notebook.ipynb_ onde reside seu arquivo _ufo-model.pkl_.
1. Nessa pasta, crie mais três pastas: **static**, com uma pasta **css** dentro dela e **templates**. Agora você deve ter os seguintes arquivos e diretórios:
```output
web-app/
static/
css/
templates/
notebook.ipynb
ufo-model.pkl
```
✅ Consulte a pasta da solução para obter uma exibição do aplicativo concluído
1. O primeiro arquivo a ser criado na pasta _web-app_ é o arquivo **requirements.txt**. Como _package.json_ em um aplicativo JavaScript, esse arquivo lista as dependências exigidas pelo aplicativo. Em **requirements.txt** adicione as linhas:
```text
scikit-learn
pandas
numpy
flask
```
1. Agora, execute este arquivo navegando para _web-app_:
```bash
cd web-app
```
1. Em seu terminal, digite `pip install` para instalar as bibliotecas listadas em _requirements.txt_:
```bash
pip install -r requirements.txt
```
1.Agora, você está pronto para criar mais três arquivos para concluir o aplicativo:
1. Crie **app.py** na raiz.
2. Crie **index.html** no diretório _templates_.
3. Crie **styles.css** no diretório _static/css_.
1. Construa o arquivo _styles.css_ com alguns estilos:
```css
body {
width: 100%;
height: 100%;
font-family: 'Helvetica';
background: black;
color: #fff;
text-align: center;
letter-spacing: 1.4px;
font-size: 30px;
}
input {
min-width: 150px;
}
.grid {
width: 300px;
border: 1px solid #2d2d2d;
display: grid;
justify-content: center;
margin: 20px auto;
}
.box {
color: #fff;
background: #2d2d2d;
padding: 12px;
display: inline-block;
}
```
1. Em seguida, crie o arquivo _index.html_:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>🛸 UFO Appearance Prediction! 👽</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
<div class="grid">
<div class="box">
<p>According to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?</p>
<form action="{{ url_for('predict')}}" method="post">
<input type="number" name="seconds" placeholder="Seconds" required="required" min="0" max="60" />
<input type="text" name="latitude" placeholder="Latitude" required="required" />
<input type="text" name="longitude" placeholder="Longitude" required="required" />
<button type="submit" class="btn">Predict country where the UFO is seen</button>
</form>
<p>{{ prediction_text }}</p>
</div>
</div>
</body>
</html>
```
Dê uma olhada na modelagem neste arquivo. Observe a sintaxe do 'bigode' ao redor das variáveis que serão fornecidas pelo aplicativo, como o texto de previsão: `{{}}`. Há também uma forma que publica uma previsão da rota `/predict`.
Finalmente, você está pronto para construir o arquivo python que direciona o consumo do modelo e a exibição de previsões:
1. Em `app.py` adicione:
```python
import numpy as np
from flask import Flask, request, render_template
import pickle
app = Flask(__name__)
model = pickle.load(open("../ufo-model.pkl", "rb"))
@app.route("/")
def home():
return render_template("index.html")
@app.route("/predict", methods=["POST"])
def predict():
int_features = [int(x) for x in request.form.values()]
final_features = [np.array(int_features)]
prediction = model.predict(final_features)
output = prediction[0]
countries = ["Australia", "Canada", "Germany", "UK", "US"]
return render_template(
"index.html", prediction_text="Likely country: {}".format(countries[output])
)
if __name__ == "__main__":
app.run(debug=True)
```
>Dica: quando você adiciona [`debug=True`](https://www.askpython.com/python-modules/flask/flask-debug-mode) ao executar o aplicativo Web usando Flask, todas as alterações feitas no aplicativo serão refletidas imediatamente sem a necessidade de reiniciar o servidor. Cuidado! Não habilite este modo em um aplicativo de produção.
Se você executar `python app.py` ou `python3 app.py` - seu servidor Web é iniciado localmente e você pode preencher um formulário curto para obter uma resposta para sua pergunta de gravação sobre onde os OVNIs foram avistados!
Antes de fazer isso, dê uma olhada nas partes de `app.py`:
1. Primeiro, as dependências são carregadas e o aplicativo inicia.
1. Então, o modelo é importado.
1. Então, index.html é renderizado na rota inicial.
Na rota `/predict`, várias coisas acontecem quando o formulário é publicado:
1. As variáveis de formulário são reunidas e convertidas em uma matriz numérica. Eles são então enviados para o modelo e uma previsão é retornada.
2. Os Países que queremos exibir são renderizados novamente como texto legível de seu código de país previsto, e esse valor é enviado de volta para index.html para ser renderizado no modelo.
Usando um modelo desta maneira, com Flask e um modelo em conserva, é relativamente simples. A coisa mais difícil é entender qual é a forma dos dados que devem ser enviados ao modelo para obter uma previsão. Tudo depende de como o modelo foi treinado. Este tem três pontos de dados para serem inseridos a fim de obter uma previsão.
Em um ambiente profissional, você pode ver como uma boa comunicação é necessária entre as pessoas que treinam o modelo e aqueles que o consomem em um aplicativo web ou móvel. No nosso caso, é só uma pessoa, você!
---
## 🚀Desafio
Em vez de trabalhar em um notebook e importar o modelo para o aplicativo Flask, você poderia treinar o modelo dentro do aplicativo Flask! Tente converter seu código Python no notebook, talvez depois que seus dados forem limpos, para treinar o modelo de dentro do aplicativo em uma rota chamada `train`. Quais são os prós e contras de se buscar esse método?
## [Teste pós-aula](https://white-water-09ec41f0f.azurestaticapps.net/quiz/18/)
## Análise e autoestudo
Há muitas maneiras de construir um aplicativo Web para consumir modelos ML. Faça uma lista de maneiras de usar JavaScript ou Python para construir um aplicativo Web para aproveitar o aprendizado de máquina. Considere a arquitetura: o modelo deve permanecer no aplicativo ou viver na nuvem? Se o último, como você acessaria? Desenhe um modelo arquitetônico para uma solução web ML aplicada.
## Atribuição
[Tente um modelo diferente](assignment.md)

@ -0,0 +1,11 @@
# Tente um modelo diferente
## Instruções
Agora que você construiu um aplicativo Web usando um modelo Regression treinado, use um dos modelos de uma lição Regression anterior para refazer esse aplicativo Web. Você pode manter o estilo ou design de forma diferente para refletir os dados da abóbora. Tenha cuidado para alterar as entradas para refletir o método de treinamento do seu modelo.
## Rubrica
| Critérios | Exemplar | Adequado | Necessidade de melhoria |
| -------------------------- | --------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------- |
| | O aplicativo Web é executado conforme o esperado e implantado na nuvem | O aplicativo Web contém falhas ou exibe resultados inesperados | O aplicativo Web não funciona corretamente|

@ -0,0 +1,21 @@
# Crie um aplicativo Web para usar seu modelo ML
Nesta seção do currículo, você será apresentado a um tópico ML aplicado: como salvar seu modelo Scikit-learn como um arquivo que pode ser usado para fazer previsões em uma aplicação Web. Uma vez que o modelo é salvo, você vai aprender como usá-lo em um aplicativo web construído em Flask. Você vai primeiro criar um modelo usando alguns dados que são tudo sobre avistamentos de UFO! Em seguida, você criará um aplicativo Web que permitirá inserir um número de segundos com uma latitude e um valor de longitude para prever qual país relatou ter visto um UFO.
![Estacionamento UFO](../images/ufo.jpg)
Foto de <a href="https://unsplash.com/@mdherren?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Michael Herren</a> em <a href="https://unsplash.com/s/photos/ufo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## Lições
1. [Crie um aplicativo Web](1-Web-App/README.md)
## Créditos
"Build a Web App" foi escrito com ♥️ por[Jen Looper](https://twitter.com/jenlooper).
♥️ Os testes foram escritos por Rohan Raj.
O conjunto de dados provém de [Kaggle](https://www.kaggle.com/NUFORC/ufo-sightings).
A arquitetura do aplicativo Web foi sugerida em parte por [este artigo](https://towardsdatascience.com/how-to-easy-deploy-machine-learning-models-using-flask-b95af8fe34d4) e [este repositório](https://github.com/abhinavsagar/machine-learning-deployment) by Abhinav Sagar.

@ -0,0 +1,386 @@
# Time Series Forecasting with Support Vector Regressor
In the previous lesson, you learned how to use ARIMA model to make time series predictions. Now you'll be looking at Support Vector Regressor model which is a regressor model used to predict continuous data.
## [Pre-lecture quiz](https://white-water-09ec41f0f.azurestaticapps.net/quiz/51/)
## Introduction
In this lesson, you will discover a specific way to build models with [**SVM**: **S**upport **V**ector **M**achine](https://en.wikipedia.org/wiki/Support-vector_machine) for regression, or **SVR: Support Vector Regressor**.
### SVR in the context of time series [^1]
Before understanding the importance of SVR in time series prediction, here are some of the important concepts that you need to know:
- **Regression:** Supervised learning technique to predict continuous values from a given set of inputs. The idea is to fit a curve (or line) in the feature space that has the maximum number of data points. [Click here](https://en.wikipedia.org/wiki/Regression_analysis) for more information.
- **Support Vector Machine (SVM):** A type of supervised machine learning model used for classification, regression and outliers detection. The model is a hyperplane in the feature space, which in case of classification acts as a boundary, and in case of regression acts as the best-fit line. In SVM, a Kernel function is generally used to transform the dataset to a space of higher number of dimensions, so that they can be easily separable. [Click here](https://en.wikipedia.org/wiki/Support-vector_machine) for more information on SVMs.
- **Support Vector Regressor (SVR):** A type of SVM, to find the best fit line (which in the case of SVM is a hyperplane) that has the maximum number of data points.
### Why SVR? [^1]
In the last lesson you learned about ARIMA, which is a very successful statistical linear method to forecast time series data. However, in many cases, time series data have *non-linearity*, which cannot be mapped by linear models. In such cases, the ability of SVM to consider non-linearity in the data for regression tasks makes SVR successful in time series forecasting.
## Exercise - build an SVR model
The first few steps for data preparation are the same as that of the previous lesson on [ARIMA](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/2-ARIMA).
Open the _/working_ folder in this lesson and find the _notebook.ipynb_ file.[^2]
1. Run the notebook and import the necessary libraries: [^2]
```python
import sys
sys.path.append('../../')
```
```python
import os
import warnings
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import datetime as dt
import math
from sklearn.svm import SVR
from sklearn.preprocessing import MinMaxScaler
from common.utils import load_data, mape
```
2. Load the data from the `/data/energy.csv` file into a Pandas dataframe and take a look: [^2]
```python
energy = load_data('../../data')[['load']]
```
3. Plot all the available energy data from January 2012 to December 2014: [^2]
```python
energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12)
plt.xlabel('timestamp', fontsize=12)
plt.ylabel('load', fontsize=12)
plt.show()
```
![full data](images/full-data.png)
Now, let's build our SVR model.
### Create training and testing datasets
Now your data is loaded, so you can separate it into train and test sets. Then you'll reshape the data to create a time-step based dataset which will be needed for the SVR. You'll train your model on the train set. After the model has finished training, you'll evaluate its accuracy on the training set, testing set and then the full dataset to see the overall performance. You need to ensure that the test set covers a later period in time from the training set to ensure that the model does not gain information from future time periods [^2] (a situation known as *Overfitting*).
1. Allocate a two-month period from September 1 to October 31, 2014 to the training set. The test set will include the two-month period of November 1 to December 31, 2014: [^2]
```python
train_start_dt = '2014-11-01 00:00:00'
test_start_dt = '2014-12-30 00:00:00'
```
2. Visualize the differences: [^2]
```python
energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \
.join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \
.plot(y=['train', 'test'], figsize=(15, 8), fontsize=12)
plt.xlabel('timestamp', fontsize=12)
plt.ylabel('load', fontsize=12)
plt.show()
```
![training and testing data](images/train-test.png)
### Prepare the data for training
Now, you need to prepare the data for training by performing filtering and scaling of your data. Filter your dataset to only include the time periods and columns you need, and scaling to ensure the data is projected in the interval 0,1.
1. Filter the original dataset to include only the aforementioned time periods per set and only including the needed column 'load' plus the date: [^2]
```python
train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']]
test = energy.copy()[energy.index >= test_start_dt][['load']]
print('Training data shape: ', train.shape)
print('Test data shape: ', test.shape)
```
```output
Training data shape: (1416, 1)
Test data shape: (48, 1)
```
2. Scale the training data to be in the range (0, 1): [^2]
```python
scaler = MinMaxScaler()
train['load'] = scaler.fit_transform(train)
```
4. Now, you scale the testing data: [^2]
```python
test['load'] = scaler.transform(test)
```
### Create data with time-steps [^1]
For the SVR, you transform the input data to be of the form `[batch, timesteps]`. So, you reshape the existing `train_data` and `test_data` such that there is a new dimension which refers to the timesteps.
```python
# Converting to numpy arrays
train_data = train.values
test_data = test.values
```
For this example, we take `timesteps = 5`. So, the inputs to the model are the data for the first 4 timesteps, and the output will be the data for the 5th timestep.
```python
timesteps=5
```
Converting training data to 2D tensor using nested list comprehension:
```python
train_data_timesteps=np.array([[j for j in train_data[i:i+timesteps]] for i in range(0,len(train_data)-timesteps+1)])[:,:,0]
train_data_timesteps.shape
```
```output
(1412, 5)
```
Converting testing data to 2D tensor:
```python
test_data_timesteps=np.array([[j for j in test_data[i:i+timesteps]] for i in range(0,len(test_data)-timesteps+1)])[:,:,0]
test_data_timesteps.shape
```
```output
(44, 5)
```
Selecting inputs and outputs from training and testing data:
```python
x_train, y_train = train_data_timesteps[:,:timesteps-1],train_data_timesteps[:,[timesteps-1]]
x_test, y_test = test_data_timesteps[:,:timesteps-1],test_data_timesteps[:,[timesteps-1]]
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
```
```output
(1412, 4) (1412, 1)
(44, 4) (44, 1)
```
### Implement SVR [^1]
Now, it's time to implement SVR. To read more about this implementation, you can refer to [this documentation](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVR.html). For our implementation, we follow these steps:
1. Define the model by calling `SVR()` and passing in the model hyperparameters: kernel, gamma, c and epsilon
2. Prepare the model for the training data by calling the `fit()` function
3. Make predictions calling the `predict()` function
Now we create an SVR model. Here we use the [RBF kernel](https://scikit-learn.org/stable/modules/svm.html#parameters-of-the-rbf-kernel), and set the hyperparameters gamma, C and epsilon as 0.5, 10 and 0.05 respectively.
```python
model = SVR(kernel='rbf',gamma=0.5, C=10, epsilon = 0.05)
```
#### Fit the model on training data [^1]
```python
model.fit(x_train, y_train[:,0])
```
```output
SVR(C=10, cache_size=200, coef0=0.0, degree=3, epsilon=0.05, gamma=0.5,
kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verbose=False)
```
#### Make model predictions [^1]
```python
y_train_pred = model.predict(x_train).reshape(-1,1)
y_test_pred = model.predict(x_test).reshape(-1,1)
print(y_train_pred.shape, y_test_pred.shape)
```
```output
(1412, 1) (44, 1)
```
You've built your SVR! Now we need to evaluate it.
### Evaluate your model [^1]
For evaluation, first we will scale back the data to our original scale. Then, to check the performance, we will plot the original and predicted time series plot, and also print the MAPE result.
Scale the predicted and original output:
```python
# Scaling the predictions
y_train_pred = scaler.inverse_transform(y_train_pred)
y_test_pred = scaler.inverse_transform(y_test_pred)
print(len(y_train_pred), len(y_test_pred))
```
```python
# Scaling the original values
y_train = scaler.inverse_transform(y_train)
y_test = scaler.inverse_transform(y_test)
print(len(y_train), len(y_test))
```
#### Check model performance on training and testing data [^1]
We extract the timestamps from the dataset to show in the x-axis of our plot. Note that we are using the first ```timesteps-1``` values as out input for the first output, so the timestamps for the output will start after that.
```python
train_timestamps = energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)].index[timesteps-1:]
test_timestamps = energy[test_start_dt:].index[timesteps-1:]
print(len(train_timestamps), len(test_timestamps))
```
```output
1412 44
```
Plot the predictions for training data:
```python
plt.figure(figsize=(25,6))
plt.plot(train_timestamps, y_train, color = 'red', linewidth=2.0, alpha = 0.6)
plt.plot(train_timestamps, y_train_pred, color = 'blue', linewidth=0.8)
plt.legend(['Actual','Predicted'])
plt.xlabel('Timestamp')
plt.title("Training data prediction")
plt.show()
```
![training data prediction](images/train-data-predict.png)
Print MAPE for training data
```python
print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')
```
```output
MAPE for training data: 1.7195710200875551 %
```
Plot the predictions for testing data
```python
plt.figure(figsize=(10,3))
plt.plot(test_timestamps, y_test, color = 'red', linewidth=2.0, alpha = 0.6)
plt.plot(test_timestamps, y_test_pred, color = 'blue', linewidth=0.8)
plt.legend(['Actual','Predicted'])
plt.xlabel('Timestamp')
plt.show()
```
![testing data prediction](images/test-data-predict.png)
Print MAPE for testing data
```python
print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')
```
```output
MAPE for testing data: 1.2623790187854018 %
```
🏆 You have a very good result on the testing dataset!
### Check model performance on full dataset [^1]
```python
# Extracting load values as numpy array
data = energy.copy().values
# Scaling
data = scaler.transform(data)
# Transforming to 2D tensor as per model input requirement
data_timesteps=np.array([[j for j in data[i:i+timesteps]] for i in range(0,len(data)-timesteps+1)])[:,:,0]
print("Tensor shape: ", data_timesteps.shape)
# Selecting inputs and outputs from data
X, Y = data_timesteps[:,:timesteps-1],data_timesteps[:,[timesteps-1]]
print("X shape: ", X.shape,"\nY shape: ", Y.shape)
```
```output
Tensor shape: (26300, 5)
X shape: (26300, 4)
Y shape: (26300, 1)
```
```python
# Make model predictions
Y_pred = model.predict(X).reshape(-1,1)
# Inverse scale and reshape
Y_pred = scaler.inverse_transform(Y_pred)
Y = scaler.inverse_transform(Y)
```
```python
plt.figure(figsize=(30,8))
plt.plot(Y, color = 'red', linewidth=2.0, alpha = 0.6)
plt.plot(Y_pred, color = 'blue', linewidth=0.8)
plt.legend(['Actual','Predicted'])
plt.xlabel('Timestamp')
plt.show()
```
![full data prediction](images/full-data-predict.png)
```python
print('MAPE: ', mape(Y_pred, Y)*100, '%')
```
```output
MAPE: 2.0572089029888656 %
```
🏆 Very nice plots, showing a model with good accuracy. Well done!
---
## 🚀Challenge
- Try to tweak the hyperparameters (gamma, C, epsilon) while creating the model and evaluate on the data to see which set of hyperparameters give the best results on the testing data. To know more about these hyperparameters, you can refer to the document [here](https://scikit-learn.org/stable/modules/svm.html#parameters-of-the-rbf-kernel).
- Try to use different kernel functions for the model and analyze their performances on the dataset. A helpful document can be found [here](https://scikit-learn.org/stable/modules/svm.html#kernel-functions).
- Try using different values for `timesteps` for the model to look back to make prediction.
## [Post-lecture quiz](https://white-water-09ec41f0f.azurestaticapps.net/quiz/52/)
## Review & Self Study
This lesson was to introduce the application of SVR for Time Series Forecasting. To read more about SVR, you can refer to [this blog](https://www.analyticsvidhya.com/blog/2020/03/support-vector-regression-tutorial-for-machine-learning/). This [documentation on scikit-learn](https://scikit-learn.org/stable/modules/svm.html) provides a more comprehensive explanation about SVMs in general, [SVRs](https://scikit-learn.org/stable/modules/svm.html#regression) and also other implementation details such as the different [kernel functions](https://scikit-learn.org/stable/modules/svm.html#kernel-functions) that can be used, and their parameters.
## Assignment
[A new SVR model](assignment.md)
## Credits
[^1]: The text, code and output in this section was contributed by [@AnirbanMukherjeeXD](https://github.com/AnirbanMukherjeeXD)
[^2]: The text, code and output in this section was taken from [ARIMA](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/2-ARIMA)

@ -0,0 +1,14 @@
# A new SVR model
## Instructions [^1]
Now that you have built an SVR model, build a new one with fresh data (try one of [these datasets from Duke](http://www2.stat.duke.edu/~mw/ts_data_sets.html). Annotate your work in a notebook, visualize the data and your model, and test its accuracy using appropriate plots and MAPE. Also try tweaking the different hyperparameters and also using different values for the timesteps.
## Rubric [^1]
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | ------------------------------------------------------------ | --------------------------------------------------------- | ----------------------------------- |
| | A notebook is presented with an SVR model built, tested and explained with visualizations and accuracy stated. | The notebook presented is not annotated or contains bugs. | An incomplete notebook is presented |
[^1]:The text in this section was based on the [assignment from ARIMA](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/2-ARIMA/assignment.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,698 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "fv9OoQsMFk5A"
},
"source": [
"# Time series prediction using Support Vector Regressor"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this notebook, we demonstrate how to:\n",
"\n",
"- prepare 2D time series data for training an SVM regressor model\n",
"- implement SVR using RBF kernel\n",
"- evaluate the model using plots and MAPE"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Importing modules"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"sys.path.append('../../')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "M687KNlQFp0-"
},
"outputs": [],
"source": [
"import os\n",
"import warnings\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"import datetime as dt\n",
"import math\n",
"\n",
"from sklearn.svm import SVR\n",
"from sklearn.preprocessing import MinMaxScaler\n",
"from common.utils import load_data, mape"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Cj-kfVdMGjWP"
},
"source": [
"## Preparing data"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8fywSjC6GsRz"
},
"source": [
"### Load data"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 363
},
"id": "aBDkEB11Fumg",
"outputId": "99cf7987-0509-4b73-8cc2-75d7da0d2740"
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>load</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2012-01-01 00:00:00</th>\n",
" <td>2698.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 01:00:00</th>\n",
" <td>2558.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 02:00:00</th>\n",
" <td>2444.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 03:00:00</th>\n",
" <td>2402.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-01 04:00:00</th>\n",
" <td>2403.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" load\n",
"2012-01-01 00:00:00 2698.0\n",
"2012-01-01 01:00:00 2558.0\n",
"2012-01-01 02:00:00 2444.0\n",
"2012-01-01 03:00:00 2402.0\n",
"2012-01-01 04:00:00 2403.0"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"energy = load_data('../../data')[['load']]\n",
"energy.head(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "O0BWP13rGnh4"
},
"source": [
"### Plot the data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 486
},
"id": "hGaNPKu_Gidk",
"outputId": "7f89b326-9057-4f49-efbe-cb100ebdf76d"
},
"outputs": [],
"source": [
"energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12)\n",
"plt.xlabel('timestamp', fontsize=12)\n",
"plt.ylabel('load', fontsize=12)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IPuNor4eGwYY"
},
"source": [
"### Create training and testing data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ysvsNyONGt0Q"
},
"outputs": [],
"source": [
"train_start_dt = '2014-11-01 00:00:00'\n",
"test_start_dt = '2014-12-30 00:00:00'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 548
},
"id": "SsfdLoPyGy9w",
"outputId": "d6d6c25b-b1f4-47e5-91d1-707e043237d7"
},
"outputs": [],
"source": [
"energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \\\n",
" .join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \\\n",
" .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12)\n",
"plt.xlabel('timestamp', fontsize=12)\n",
"plt.ylabel('load', fontsize=12)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XbFTqBw6G1Ch"
},
"source": [
"### Preparing data for training"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, you need to prepare the data for training by performing filtering and scaling of your data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cYivRdQpHDj3",
"outputId": "a138f746-461c-4fd6-bfa6-0cee094c4aa1"
},
"outputs": [],
"source": [
"train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']]\n",
"test = energy.copy()[energy.index >= test_start_dt][['load']]\n",
"\n",
"print('Training data shape: ', train.shape)\n",
"print('Test data shape: ', test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Scale the data to be in the range (0, 1)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 363
},
"id": "3DNntGQnZX8G",
"outputId": "210046bc-7a66-4ccd-d70d-aa4a7309949c"
},
"outputs": [],
"source": [
"scaler = MinMaxScaler()\n",
"train['load'] = scaler.fit_transform(train)\n",
"train.head(5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 206
},
"id": "26Yht-rzZexe",
"outputId": "20326077-a38a-4e78-cc5b-6fd7af95d301"
},
"outputs": [],
"source": [
"test['load'] = scaler.transform(test)\n",
"test.head(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "x0n6jqxOQ41Z"
},
"source": [
"### Creating data with time-steps"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fdmxTZtOQ8xs"
},
"source": [
" For our SVR, we transform the input data to be of the form `[batch, timesteps]`. So, we reshape the existing `train_data` and `test_data` such that there is a new dimension which refers to the timesteps. For our example, we take `timesteps = 5`. So, the inputs to the model are the data for the first 4 timesteps, and the output will be the data for the 5<sup>th</sup> timestep."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Rpju-Sc2HFm0"
},
"outputs": [],
"source": [
"# Converting to numpy arrays\n",
"\n",
"train_data = train.values\n",
"test_data = test.values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Selecting the timesteps\n",
"\n",
"timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "O-JrsrsVJhUQ",
"outputId": "c90dbe71-bacc-4ec4-b452-f82fe5aefaef"
},
"outputs": [],
"source": [
"# Converting data to 2D tensor\n",
"\n",
"train_data_timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "exJD8AI7KE4g",
"outputId": "ce90260c-f327-427d-80f2-77307b5a6318"
},
"outputs": [],
"source": [
"# Converting test data to 2D tensor\n",
"\n",
"test_data_timesteps=None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2u0R2sIsLuq5"
},
"outputs": [],
"source": [
"x_train, y_train = None\n",
"x_test, y_test = None\n",
"\n",
"print(x_train.shape, y_train.shape)\n",
"print(x_test.shape, y_test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8wIPOtAGLZlh"
},
"source": [
"## Creating SVR model"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "EhA403BEPEiD"
},
"outputs": [],
"source": [
"# Create model using RBF kernel\n",
"\n",
"model = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "GS0UA3csMbqp",
"outputId": "d86b6f05-5742-4c1d-c2db-c40510bd4f0d"
},
"outputs": [],
"source": [
"# Fit model on training data"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Rz_x8S3UrlcF"
},
"source": [
"### Make model prediction"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "XR0gnt3MnuYS",
"outputId": "157e40ab-9a23-4b66-a885-0d52a24b2364"
},
"outputs": [],
"source": [
"# Making predictions\n",
"\n",
"y_train_pred = None\n",
"y_test_pred = None"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_2epncg-SGzr"
},
"source": [
"## Analyzing model performance"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Scaling the predictions\n",
"\n",
"y_train_pred = scaler.inverse_transform(y_train_pred)\n",
"y_test_pred = scaler.inverse_transform(y_test_pred)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xmm_YLXhq7gV",
"outputId": "18392f64-4029-49ac-c71a-a4e2411152a1"
},
"outputs": [],
"source": [
"# Scaling the original values\n",
"\n",
"y_train = scaler.inverse_transform(y_train)\n",
"y_test = scaler.inverse_transform(y_test)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "u3LBj93coHEi",
"outputId": "d4fd49e8-8c6e-4bb0-8ef9-ca0b26d725b4"
},
"outputs": [],
"source": [
"# Extract the timesteps for x-axis\n",
"\n",
"train_timestamps = None\n",
"test_timestamps = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(25,6))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.title(\"Training data prediction\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "LnhzcnYtXHCm",
"outputId": "f5f0d711-f18b-4788-ad21-d4470ea2c02b"
},
"outputs": [],
"source": [
"print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 225
},
"id": "53Q02FoqQH4V",
"outputId": "53e2d59b-5075-4765-ad9e-aed56c966583"
},
"outputs": [],
"source": [
"plt.figure(figsize=(10,3))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "clOAUH-SXCJG",
"outputId": "a3aa85ff-126a-4a4a-cd9e-90b9cc465ef5"
},
"outputs": [],
"source": [
"print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "DHlKvVCId5ue"
},
"source": [
"## Full dataset prediction"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cOFJ45vreO0N",
"outputId": "35628e33-ecf9-4966-8036-f7ea86db6f16"
},
"outputs": [],
"source": [
"# Extracting load values as numpy array\n",
"data = None\n",
"\n",
"# Scaling\n",
"data = None\n",
"\n",
"# Transforming to 2D tensor as per model input requirement\n",
"data_timesteps=None\n",
"\n",
"# Selecting inputs and outputs from data\n",
"X, Y = None, None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ESSAdQgwexIi"
},
"outputs": [],
"source": [
"# Make model predictions\n",
"\n",
"# Inverse scale and reshape\n",
"Y_pred = None\n",
"Y = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 328
},
"id": "M_qhihN0RVVX",
"outputId": "a89cb23e-1d35-437f-9d63-8b8907e12f80"
},
"outputs": [],
"source": [
"plt.figure(figsize=(30,8))\n",
"# plot original output\n",
"# plot predicted output\n",
"plt.legend(['Actual','Predicted'])\n",
"plt.xlabel('Timestamp')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AcN7pMYXVGTK",
"outputId": "7e1c2161-47ce-496c-9d86-7ad9ae0df770"
},
"outputs": [],
"source": [
"print('MAPE: ', mape(Y_pred, Y)*100, '%')"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"collapsed_sections": [],
"name": "Recurrent_Neural_Networks.ipynb",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

@ -16,7 +16,8 @@ Photo by <a href="https://unsplash.com/@shutter_log?utm_source=unsplash&utm_medi
1. [Introduction to time series forecasting](1-Introduction/README.md)
2. [Building ARIMA time series models](2-ARIMA/README.md)
3. [Building Support Vector Regressor for time series forcasting](3-SVR/README.md)
## Credits
"Introduction to time series forecasting" was written with ⚡️ by [Francesca Lazzeri](https://twitter.com/frlazzeri) and [Jen Looper](https://twitter.com/jenlooper). The notebooks first appeared online in the [Azure "Deep Learning For Time Series" repo](https://github.com/Azure/DeepLearningForTimeSeriesForecasting) originally written by Francesca Lazzeri.
"Introduction to time series forecasting" was written with ⚡️ by [Francesca Lazzeri](https://twitter.com/frlazzeri) and [Jen Looper](https://twitter.com/jenlooper). The notebooks first appeared online in the [Azure "Deep Learning For Time Series" repo](https://github.com/Azure/DeepLearningForTimeSeriesForecasting) originally written by Francesca Lazzeri. The SVR lesson was written by [Anirban Mukherjee](https://github.com/AnirbanMukherjeeXD)

@ -0,0 +1,147 @@
import numpy as np
import pandas as pd
import os
from collections import UserDict
def load_data(data_dir):
"""Load the GEFCom 2014 energy load data"""
energy = pd.read_csv(os.path.join(data_dir, 'energy.csv'), parse_dates=['timestamp'])
# Reindex the dataframe such that the dataframe has a record for every time point
# between the minimum and maximum timestamp in the time series. This helps to
# identify missing time periods in the data (there are none in this dataset).
energy.index = energy['timestamp']
energy = energy.reindex(pd.date_range(min(energy['timestamp']),
max(energy['timestamp']),
freq='H'))
energy = energy.drop('timestamp', axis=1)
return energy
def mape(predictions, actuals):
"""Mean absolute percentage error"""
predictions = np.array(predictions)
actuals = np.array(actuals)
return (np.absolute(predictions - actuals) / actuals).mean()
def create_evaluation_df(predictions, test_inputs, H, scaler):
"""Create a data frame for easy evaluation"""
eval_df = pd.DataFrame(predictions, columns=['t+'+str(t) for t in range(1, H+1)])
eval_df['timestamp'] = test_inputs.dataframe.index
eval_df = pd.melt(eval_df, id_vars='timestamp', value_name='prediction', var_name='h')
eval_df['actual'] = np.transpose(test_inputs['target']).ravel()
eval_df[['prediction', 'actual']] = scaler.inverse_transform(eval_df[['prediction', 'actual']])
return eval_df
class TimeSeriesTensor(UserDict):
"""A dictionary of tensors for input into the RNN model.
Use this class to:
1. Shift the values of the time series to create a Pandas dataframe containing all the data
for a single training example
2. Discard any samples with missing values
3. Transform this Pandas dataframe into a numpy array of shape
(samples, time steps, features) for input into Keras
The class takes the following parameters:
- **dataset**: original time series
- **target** name of the target column
- **H**: the forecast horizon
- **tensor_structures**: a dictionary describing the tensor structure of the form
{ 'tensor_name' : (range(max_backward_shift, max_forward_shift), [feature, feature, ...] ) }
if features are non-sequential and should not be shifted, use the form
{ 'tensor_name' : (None, [feature, feature, ...])}
- **freq**: time series frequency (default 'H' - hourly)
- **drop_incomplete**: (Boolean) whether to drop incomplete samples (default True)
"""
def __init__(self, dataset, target, H, tensor_structure, freq='H', drop_incomplete=True):
self.dataset = dataset
self.target = target
self.tensor_structure = tensor_structure
self.tensor_names = list(tensor_structure.keys())
self.dataframe = self._shift_data(H, freq, drop_incomplete)
self.data = self._df2tensors(self.dataframe)
def _shift_data(self, H, freq, drop_incomplete):
# Use the tensor_structures definitions to shift the features in the original dataset.
# The result is a Pandas dataframe with multi-index columns in the hierarchy
# tensor - the name of the input tensor
# feature - the input feature to be shifted
# time step - the time step for the RNN in which the data is input. These labels
# are centred on time t. the forecast creation time
df = self.dataset.copy()
idx_tuples = []
for t in range(1, H+1):
df['t+'+str(t)] = df[self.target].shift(t*-1, freq=freq)
idx_tuples.append(('target', 'y', 't+'+str(t)))
for name, structure in self.tensor_structure.items():
rng = structure[0]
dataset_cols = structure[1]
for col in dataset_cols:
# do not shift non-sequential 'static' features
if rng is None:
df['context_'+col] = df[col]
idx_tuples.append((name, col, 'static'))
else:
for t in rng:
sign = '+' if t > 0 else ''
shift = str(t) if t != 0 else ''
period = 't'+sign+shift
shifted_col = name+'_'+col+'_'+period
df[shifted_col] = df[col].shift(t*-1, freq=freq)
idx_tuples.append((name, col, period))
df = df.drop(self.dataset.columns, axis=1)
idx = pd.MultiIndex.from_tuples(idx_tuples, names=['tensor', 'feature', 'time step'])
df.columns = idx
if drop_incomplete:
df = df.dropna(how='any')
return df
def _df2tensors(self, dataframe):
# Transform the shifted Pandas dataframe into the multidimensional numpy arrays. These
# arrays can be used to input into the keras model and can be accessed by tensor name.
# For example, for a TimeSeriesTensor object named "model_inputs" and a tensor named
# "target", the input tensor can be acccessed with model_inputs['target']
inputs = {}
y = dataframe['target']
y = y.as_matrix()
inputs['target'] = y
for name, structure in self.tensor_structure.items():
rng = structure[0]
cols = structure[1]
tensor = dataframe[name][cols].as_matrix()
if rng is None:
tensor = tensor.reshape(tensor.shape[0], len(cols))
else:
tensor = tensor.reshape(tensor.shape[0], len(cols), len(rng))
tensor = np.transpose(tensor, axes=[0, 2, 1])
inputs[name] = tensor
return inputs
def subset_data(self, new_dataframe):
# Use this function to recreate the input tensors if the shifted dataframe
# has been filtered.
self.dataframe = new_dataframe
self.data = self._df2tensors(self.dataframe)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,320 @@
# 强化学习和 Q-Learning 介绍
![机器学习中的强化学习总结](../../../sketchnotes/ml-reinforcement.png)
> 作者 [Tomomi Imura](https://www.twitter.com/girlie_mac)
强化学习涉及三个重要概念:代理、一些状态和每个状态的一组动作。通过在指定状态下执行一个动作,代理会得到奖励。想象一下电脑游戏超级马里奥。你是马里奥,你在一个游戏关卡中,站在悬崖边上。在你上面是一枚硬币。你是马里奥,在游戏关卡里,在特定位置......这就是你的状态。向右移动一步(一个动作)会让跌下悬崖,而且会得到一个低分。然而,按下跳跃按钮会让你活下来并得分。这是一个积极的结果,它会给你一个积极、正向的分数。
通过使用强化学习和模拟器(游戏),你可以学习如何玩游戏以最大化奖励,既能够活下去还可以获得尽可能多的积分。
[![强化学习简介](https://img.youtube.com/vi/lDq_en8RNOo/0.jpg)](https://www.youtube.com/watch?v=lDq_en8RNOo)
> 🎥 点击上图观看 Dmitry 讨论强化学习
## [课前测验](https://white-water-09ec41f0f.azurestaticapps.net/quiz/45/)
## 先决条件和设置
在本课中,我们将用 Python 代码做一些试验。你应该能够在你的计算机上或云中的某个地方运行本课程中的 Jupyter Notebook 代码。
你可以打开[课本笔记本](../notebook.ipynb) 并通过学习本课进行编译、运行。
> **注意:** 如果你是从云端打开此代码,你还需要获取笔记本代码中使用的 [`rlboard.py`](../rlboard.py) 文件。将其添加到与笔记本相同的目录中。
## 介绍
在本课中,我们将探索 **[彼得与狼](https://en.wikipedia.org/wiki/Peter_and_the_Wolf)** 的世界,其灵感来自俄罗斯作曲家 [Sergei Prokofiev](https://en.wikipedia.org/wiki/Sergei_Prokofiev)的音乐童话。我们将使用**强化学习**让彼得探索他的环境,收集美味的苹果并避免遇到狼。
**强化学习**RL是一种学习技术它允许我们通过运行许多实验来学习**代理**在某些**环境**中的最佳行为。这种环境中的代理应该有一些**目标**,由**奖励函数**定义。
## 环境
为简单起见,让我们将 Peter 的世界视为一个大小为 `width` x `height` 的方板,如下所示:
![彼得的环境](../images/environment.png)
该板中的每个单元格可以是:
* **地面**,彼得和其他生物可以在上面行走。
* **水**,不能在上面行走。
* **树**或**草**,可以休息的地方。
* **苹果**,代表彼得希望找到用来喂饱自己的食物。
* **狼**,这是危险的,应该避免遇到。
有一个单独的 Python 模块 [`rlboard.py`](../rlboard.py),其中包含在此环境中工作的代码。因为这段代码对于理解我们的概念并不重要,我们将导入该模块并使用它来创建示例板(代码块 1
```python
from rlboard import *
width, height = 8,8
m = Board(width,height)
m.randomize(seed=13)
m.plot()
```
这段代码会打印一张类似于上面的环境图片。
## 行动和策略
在我们的例子中,彼得的目标是找到苹果,同时避开狼和其他障碍物。为此,他可以四处走动,直到找到一个苹果。
因此,在任何位置,他都可以选择以下动作之一:向上、向下、向左和向右。
我们将这些动作定义为字典,并将它们映射到相应的坐标变化对。例如,向右移动 (`R`) 将对应于一对 `(1,0)`。(代码块 2
```python
actions = { "U" : (0,-1), "D" : (0,1), "L" : (-1,0), "R" : (1,0) }
action_idx = { a : i for i,a in enumerate(actions.keys()) }
```
综上所述,本场景的策略和目标如下:
- 我们的代理(彼得)的**策略**由一个函数定义,它返回任何给定状态下的动作。在我们的例子中,问题的状态由棋盘表示,包括玩家的当前位置。
- **目标**,强化学习的目的是学习一个好的策略,使我们能够有效地解决问题。但是,作为基准,让我们考虑称为 **随机走动** 的最简单策略。
## 随机走动
让我们首先通过实施随机走动策略来解决我们的问题。通过随机走动,我们从允许的动作中随机选择下一个动作,直到我们找到苹果(代码块 3
1. 使用以下代码实现随机走动:
```python
def random_policy(m):
return random.choice(list(actions))
def walk(m,policy,start_position=None):
n = 0 # number of steps
# set initial position
if start_position:
m.human = start_position
else:
m.random_start()
while True:
if m.at() == Board.Cell.apple:
return n # success!
if m.at() in [Board.Cell.wolf, Board.Cell.water]:
return -1 # eaten by wolf or drowned
while True:
a = actions[policy(m)]
new_pos = m.move_pos(m.human,a)
if m.is_valid(new_pos) and m.at(new_pos)!=Board.Cell.water:
m.move(a) # do the actual move
break
n+=1
walk(m,random_policy)
```
`walk` 的调用应返回相应路径的长度,该长度可能因每次运行而不同。
1. 多次运行该实验(例如 100 次),并打印结果统计信息(代码块 4
```python
def print_statistics(policy):
s,w,n = 0,0,0
for _ in range(100):
z = walk(m,policy)
if z<0:
w+=1
else:
s += z
n += 1
print(f"Average path length = {s/n}, eaten by wolf: {w} times")
print_statistics(random_policy)
```
请注意,一条路径的平均长度约为 30-40 步,考虑到到最近苹果的平均距离约为 5-6 步,这一数字相当大。
你还可以看到 Peter 在随机走动过程中的运动情况:
![彼得的随机走动](../images/random_walk.gif)
## 奖励函数
为了使我们的策略更加智能,我们需要了解哪些动作比其他动作 "更好"。为此,我们需要定义我们的目标。
可以根据**奖励函数**来定义目标,该函数将为每个状态返回一些分数值。数字越大,奖励函数越好。(代码块 5
```python
move_reward = -0.1
goal_reward = 10
end_reward = -10
def reward(m,pos=None):
pos = pos 或 m.human
if not m.is_valid(pos):
return end_reward
x = m.at(pos)
if x==Board.Cell.water or x == Board.Cell.wolf
return end_reward
if x==Board.Cell.apple
return goal_reward
return move_reward
```
关于奖励函数的一个有趣的事情是,在大多数情况下,*我们只在游戏结束时才得到实质性的奖励*。这意味着我们的算法应该以某种方式记住最终导致积极奖励的"好"步骤,并增加它们的重要性。同样,所有导致不良结果的举动都应该被阻拦。
## Q-Learning
我们将在这里讨论的一种叫做 **Q-Learning** 的算法。在该算法中,策略由称为 **Q-Table** 的函数(或数据结构)定义。它记录了给定状态下每个动作的"优点"。
之所以称为 Q-Table是因为表格或多维数组通常表示起来很方便。由于我们的棋盘尺寸为 "width"x"height",我们可以使用形状为 "width"x"height"x"len(actions) 的 numpy 数组来表示 Q-Table代码块6
```python
Q = np.ones((width,height,len(actions)),dtype=np.float)*1.0/len(actions)
```
请注意,我们将 Q-Table 的所有值初始化为一个相等的值,在我们的例子中为 "-0.25"。这对应于"随机走动"策略,因为每个状态中的所有移动都同样好。我们可以将 Q-Table 传递给 `plot` 函数,以便在板上可视化表格:`m.plot(Q)`。
![彼得的环境](../images/env_init.png)
在每个单元格的中心有一个"箭头",表示首选的移动方向。由于所有方向都相等,因此显示一个点。
现在我们需要运行这个程序,探索我们的环境,并学习更好的 Q-Table 值分布,这将使我们能够更快地找到通往苹果的路径。
## Q-Learning 的本质:贝尔曼方程
一旦我们开始移动,每个动作都会有相应的奖励,即理论上我们可以根据最高的即时奖励来选择下一个动作。但是,在大多数情况,此举不会实现我们到达苹果的目标,因此我们无法立即决定哪个方向更好。
> 请记住,重要的不是直接结果,而是我们将在模拟结束时获得的最终结果。
为了解释这种延迟奖励,我们需要使用**[动态规划](https://en.wikipedia.org/wiki/Dynamic_programming)** 的原则,它允许我们递归地思考问题。
假设我们现在处于状态 *s*,并且我们想要移动到下一个状态 *s'*。通过这样做,我们将收到由奖励函数定义的即时奖励 *r(s,a)*,以及一些未来的奖励。如果我们假设我们的 Q-Table 正确反映了每个动作的“吸引力”,那么在状态 *s'* 我们将选择对应于 *Q(s',a')* 最大值的动作 *a*。因此,我们可以在状态 *s* 获得的最佳未来奖励将被定义为 `max`<sub>a'</sub>*Q(s',a')*(这里的最大值是在状态 *s'* 时所有可能的动作 *a'* 上计算的)。
这给出了 **Bellman 公式**,用于计算状态 *s* 的 Q-Table 值,给定动作 *a*
<img src="../images/bellmaneq.gif"/>
这里 γ 是所谓的**折扣因子**,它决定了你应该在多大程度上更喜欢当前的奖励而不是未来的奖励,反之亦然。
## 学习算法
鉴于上面的等式,我们现在可以为我们的学习算法编写伪代码:
* 用相同的数字为所有状态和动作初始化 Q-Table Q
* 设置学习率α ← 1
* 多次重复模拟
1. 随机位置开始
1. 重复
1. 在状态 *s* 选择一个动作 *a*
2.通过移动到新状态 *s'* 来执行动作
3.如果我们遇到游戏结束的情况,或者总奖励太少——退出模拟
4. 计算新状态下的奖励 *r*
5. 根据 Bellman 方程更新 Q-Function *Q(s,a)* ← *(1-α)Q(s,a)+α(r+γ max<sub>a'</sub>Q( s',a'))*
6. *s* ← *s'*
7. 更新总奖励并减少 α。
## 利用与探索
在上面的算法中,我们没有指定在步骤 2.1 中我们应该如何选择一个动作。如果我们随机选择动作,我们会随机**探索**环境,我们很可能会经常死亡以及探索我们通常不会去的区域。另一种方法是**利用**我们已经知道的 Q-Table 值,从而在状态 *s* 选择最佳动作(具有更高的 Q-Table 值)。然而,这将阻止我们探索其他状态,而且我们可能找不到最佳解决方案。
因此,最好的方法是在探索和开发之间取得平衡。这可以通过选择状态 *s* 的动作来完成,概率与 Q 表中的值成正比。一开始,当 Q-Table 值都相同时,它将对应于随机选择,但是随着我们对环境的了解越来越多,我们将更有可能遵循最佳路线,同时允许智能体偶尔选择未探索的路径。
## Python 实现
我们现在准备实现学习算法。在我们这样做之前,我们还需要一些函数来将 Q-Table 中的任意数字转换为相应动作的概率向量。
1. 创建一个函数 `probs()`
```python
def probs(v,eps=1e-4):
v = vv.min()+eps
v = v/v.sum()
return v
```
我们向原始向量添加了一些 `eps`,以避免在初始情况下被 0 除,此时向量的所有分量都相同。
通过 5000 次实验运行他们的学习算法,也称为 **epochs**:(代码块 8
```python
for epoch in range(5000):
# Pick initial point
m.random_start()
# Start travelling
n=0
cum_reward = 0
while True:
x,y = m.human
v = probs(Q[x,y])
a = random.choices(list(actions),weights=v)[0]
dpos = actions[a]
m.move(dpos,check_correctness=False) # we allow player to move outside the board, which terminates episode
r = reward(m)
cum_reward += r
if r==end_reward or cum_reward < -1000:
lpath.append(n)
break
alpha = np.exp(-n / 10e5)
gamma = 0.5
ai = action_idx[a]
Q[x,y,ai] = (1 - alpha) * Q[x,y,ai] + alpha * (r + gamma * Q[x+dpos[0], y+dpos[1]].max())
n+=1
```
执行此算法后,应使用定义每个步骤不同动作的吸引力的值更新 Q-Table 。我们可以尝试通过在每个单元格上绘制一个向量来可视化 Q-Table该向量将指向所需的移动方向。为简单起见我们画一个小圆圈而不是箭头。
<img src="../images/learned.png"/>
## 检查策略
由于 Q-Table 列出了每个状态下每个动作的"吸引力",因此很容易使用它来定义我们世界中的高效导航。在最简单的情况下,我们可以选择最高 Q-Table 值对应的 action代码块9
```python
def qpolicy_strict(m):
x,y = m.human
v = probs(Q[x,y])
a = list(actions)[np.argmax(v)]
return a
walk(m,qpolicy_strict)
```
> 如果你多次尝试上面的代码,你可能会注意到它有时会"挂起",你需要按笔记本中的 STOP 按钮来中断它。发生这种情况是因为可能存在两种状态在最佳 Q 值方面"指向"彼此的情况,在这种情况下,代理最终会在这些状态之间无限期地移动。
## 🚀挑战
> **任务 1** 修改 `walk` 函数,将路径的最大长度限制为一定的步数(比如 100并时不时地观察上面的代码返回值。
> **任务 2** 修改 `walk` 函数,使其不会回到之前已经去过的地方。这将防止 `walk` 循环,但是,代理仍然可能最终"被困"在它无法逃脱的位置。
## 导航
更好的导航策略是我们在训练期间使用的,它结合了利用和探索。在这个策略中,我们将以一定的概率选择每个动作,与 Q-Table 中的值成比例。这种策略可能仍会导致代理返回到它已经探索过的位置,但是,正如你从下面的代码中看到的,它会导致到达所需位置的平均路径非常短(请记住,`print_statistics` 运行模拟100次代码块10
```python
def qpolicy(m):
x,y = m.human
v = probs(Q[x,y])
a = random.choices(list(actions),weights=v)[0]
return a
print_statistics(qpolicy)
```
运行此代码后,你应该获得比以前小得多的平均路径长度,范围为 3-6。
## 调查学习过程
正如我们已经提到的,学习过程是探索和探索有关问题空间结构的知识之间的平衡。我们已经看到学习的结果(帮助代理找到到达目标的短路径的能力)有所改善,但观察平均路径长度在学习过程中的表现也很有趣:
<img src="../images/lpathlen1.png"/>
学习内容可以概括为:
- **平均路径长度增加**。我们在这里看到的是,起初,平均路径长度增加。这可能是因为当我们对环境一无所知时,我们很可能会陷入糟糕的状态,水或狼。随着我们学习更多并开始使用这些知识,我们可以更长时间地探索环境,但我们仍然不知道苹果在哪里。
- **随着我们了解更多,路径长度减少**。一旦我们学习得足够多,代理就更容易实现目标,路径长度开始减少。然而,我们仍然对探索持开放态度,因此我们经常偏离最佳路径,并探索新的选择,使路径比最佳路径更长。
- **长度突然增加**。我们在这张图上还观察到,在某个时刻,长度突然增加。这表明该过程的随机性,我们可以在某个时候通过用新值覆盖 Q-Table 系数来"破坏" Q-Table 系数。理想情况下,这应该通过降低学习率来最小化(例如,在训练结束时,我们只调整 Q-Table 很小的一个小值)。
总的来说,重要的是要记住学习过程的成功和质量在很大程度上取决于参数,例如学习率、学习率衰减和折扣因子。这些通常称为**超参数**,以区别于我们在训练期间优化的**参数**例如Q-Table 系数)。寻找最佳超参数值的过程称为**超参数优化**,它值得一个单独的话题来介绍。
## [课后测验](https://white-water-09ec41f0f.azurestaticapps.net/quiz/46/)
## 作业[一个更真实的世界](assignment.zh-cn.md)

@ -0,0 +1,27 @@
# 一个更真实的世界
我们假想,彼得几乎可以一直走动而不会感到疲倦或饥饿。但在一个更真实的世界里,我们需要时不时地坐下来休息,也要吃东西。让我们加入以下规则让我们的世界更真实:
1. 从一个地方走到另一个地方,彼得失去了**能量**并获得了一些**疲惫**。
2. 彼得可以通过吃苹果来获得更多的能量。
3. 彼得可以通过在树下或草地上休息来消除疲惫(即走进有树和草的棋盘位置——绿色的格子)
4. 彼得需要找到并杀死狼
5. 为了杀死狼,彼得需要有一定级别的能量和疲惫,否则他会输掉这场战斗。
## 说明
使用原始 [notebook.ipynb](../notebook.ipynb) 笔记本作为解决方案的起点。
根据游戏规则修改上面的奖励函数,运行强化学习算法来学习赢得游戏的最佳策略,并在游戏赢/输的数量上将你的算法和随机走动算法进行对比。
> **注意**在你的新世界中状态更加复杂除了人体位置还包括疲惫和能量水平。你可以选择将状态表示为一个元组Board、energy、fatigue或者为状态定义一个类你可能还想从 `Board` 派生它),甚至在 [rlboard.py](../rlboard.py)中修改`Board`的源码。
在你的解决方案中,请保留负责随机走动策略的代码,并在最后将你的算法与随机走动算法进行比较。
> **注意**:你可能需要调整超参数才能使其工作,尤其是 epoch 数。因为游戏的成功(与狼搏斗)是一个罕见的事件,你需要更长的训练时间。
## 评判标准
| 标准 | 优秀 | 中规中矩 | 仍需努力 |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| |笔记本上有新世界规则的定义、Q-Learning 算法和一些文字解释。与随机游走相比Q-Learning 能够显著改善结果 | 介绍了 Notebook实现了 Q-Learning 并与随机走动算法相比提高了结果,但不显著;或者 notebook 的文档不完善,代码结构不合理 | 一些试图重新定义世界规则的尝试,但 Q-Learning 算法不起作用,或者奖励函数没有完全定义 |

@ -0,0 +1,341 @@
# CartPole Skating
我们在上一课中一直在解决的问题可能看起来像一个玩具问题,并不真正适用于现实生活场景。事实并非如此,因为许多现实世界的问题也有这种情况——包括下国际象棋或围棋。它们很相似,因为我们也有一个具有给定规则和**离散状态**的板。
https://white-water-09ec41f0f.azurestaticapps.net/
## [课前测验](https://white-water-09ec41f0f.azurestaticapps.net/quiz/47/)
## 介绍
在本课中,我们将把 Q-Learning 的相同原理应用到具有**连续状态**的问题,比如由一个或多个实数给出的状态。我们将处理以下问题:
> **问题**:如果彼得想要逃离狼群,他需要能够移动得更快。我们将看到彼得如何使用 Q-Learning 学习滑冰,特别是保持平衡。
![大逃亡!](../images/escape.png)
> 彼得和他的朋友们发挥创意来逃离狼!图片来自 [Jen Looper](https://twitter.com/jenlooper)
我们将使用称为 **CartPole** 问题的简化版版本。在这个世界中,我们有一个可以左右移动的水平滑块,目标是平衡滑块顶部的垂直杆。
<img alt="a cartpole" src="../images/cartpole.png" width="200"/>
## 先决条件
在本课中,我们将使用一个名为 **OpenAI Gym** 的库来模拟不同的 **环境**。你可以在本地(例如从 Visual Studio Code运行本课程的代码在这种情况下模拟将在新窗口中打开。在线运行代码时你可能需要对代码进行一些调整如 [此处](https://towardsdatascience.com/rendering-openai-gym-envs-on-binder-and-google-colab-536f99391cc7)。
## OpenAI Gym
在上一课中,游戏规则和状态是由我们自己定义的"Board"类给出的。这里我们将使用一个特殊的**模拟环境**,它将模拟平衡杆后面的物理规则。训练强化学习算法最流行的模拟环境之一称为 [Gym](https://gym.openai.com/),由 [OpenAI](https://openai.com/) 维护。通过使用这个模拟环境,我们可以创建不同的**环境**,从推车模拟到 Atari 游戏。
> **注意**:你可以在 [此处](https://gym.openai.com/envs/#classic_control) 查看 OpenAI Gym 提供的其他环境。
首先,让我们安装 gym 并导入所需的库(代码块 1
```python
import sys
!{sys.executable} -m pip install gym
import gym
import matplotlib.pyplot as plt
import numpy as np
import random
```
## 练习 - 初始化一个推车环境
为了解决车杆平衡问题,我们需要初始化相应的环境。每个环境都有以下内容:
- **观察空间**,定义了我们从环境中接收到的信息结构。对于 cartpole 问题,我们接收杆的位置、速度和其他一些值。
- **动作空间**,定义可能的动作。在我们的例子中,动作空间是离散的,由两个动作组成 - **left****right**。(代码块 2
1. 要初始化,请键入以下代码:
```python
env = gym.make("CartPole-v1")
print(env.action_space)
print(env.observation_space)
print(env.action_space.sample())
```
要查看环境如何工作,让我们运行 100 个步骤的简短模拟。在每一步,我们提供一个要采取的行动——在这个模拟中,我们只是从 "action_space" 中随机选择一个行动。
1. 运行下面的代码,看看它会导致什么。
✅ 请记住,最好在本地 Python 安装上运行此代码!(代码块 3
```python
env.reset()
for i in range(100):
env.render()
env.step(env.action_space.sample())
env.close()
```
你应该会看到与此图像类似的内容:
![非平衡cartpole](../images/cartpole-nobalance.gif)
2. 在模拟过程中我们需要通过观察来决定如何行动。事实上step 函数返回当前观察值、奖励函数和指示是否继续模拟有意义的完成标志:(代码块 4
```python
env.reset()
done = False
while not done:
env.render()
obs, rew, done, info = env.step(env.action_space.sample())
print(f"{obs} -> {rew}")
env.close()
```
你最终会在笔记本输出中看到类似的内容:
```text
[ 0.03403272 -0.24301182 0.02669811 0.2895829 ] -> 1.0
[ 0.02917248 -0.04828055 0.03248977 0.00543839] -> 1.0
[ 0.02820687 0.14636075 0.03259854 -0.27681916] -> 1.0
[ 0.03113408 0.34100283 0.02706215 -0.55904489] -> 1.0
[ 0.03795414 0.53573468 0.01588125 -0.84308041] -> 1.0
...
[ 0.17299878 0.15868546 -0.20754175 -0.55975453] -> 1.0
[ 0.17617249 0.35602306 -0.21873684 -0.90998894] -> 1.0
```
在模拟的每一步返回的观察向量包含以下值:
- 推车的位置
- 推车速度
- 杆的角度
- 杆的转速
1. 获取这些数字的最小值和最大值:(代码块 5
```python
print(env.observation_space.low)
print(env.observation_space.high)
```
你可能还注意到,每个模拟步骤的奖励值始终为 1。这是因为我们的目标是尽可能长时间地生存即在最长的时间内将杆保持在合理的垂直位置。
✅ 事实上,如果我们设法在 100 次连续试验中获得 195 的平均奖励,则认为 CartPole 问题已解决。
## 状态离散化
在 Q-Learning 中,我们需要构建 Q-Table 来定义在每个状态下要做什么。为了能够做到这一点,我们需要状态 **discreet**,更准确地说,它应该包含有限数量的离散值。因此,我们需要以某种方式**离散**我们的观察,将它们映射到一组有限的状态。
我们有几种方法可以做到这一点:
- **拆分装箱**。如果我们知道某个值的区间,我们可以把这个区间分成若干个**bins**,然后用它所属的箱子序号替换这个值。这可以使用 [`digitize`](https://numpy.org/doc/stable/reference/generated/numpy.digitize.html) 方法来完成。在这种情况下,我们将精确地知道状态大小,因为它取决于我们选择的箱子数量。
✅ 我们可以使用线性插值将值带入某个有限区间(例如,从 -20 到 20然后通过四舍五入将数字转换为整数。这使我们对状态大小的控制减弱了一点尤其是当我们不知道输入值的确切范围时。例如在我们的例子中4 个值中有 2 个值的值没有上限/下限,这可能会导致无限数量的状态。
在我们的示例中,我们将采用第二种方法。稍后你可能会注意到,尽管有未定义的上限/下限,但这些值很少采用某些有限区间之外的值,因此具有极值的状态将非常罕见。
1. 这是一个函数,它将从我们的模型中获取观察结果并生成一个包含 4 个整数值的元组:(代码块 6
```python
def discretize(x):
return tuple((x/np.array([0.25, 0.25, 0.01, 0.1])).astype(np.int))
```
2. 让我们也探索另一种使用 bins 的离散化方法:(代码块 7
```python
def create_bins(i,num):
return np.arange(num+1)*(i[1]-i[0])/num+i[0]
print("Sample bins for interval (-5,5) with 10 bins\n",create_bins((-5,5),10))
ints = [(-5,5),(-2,2),(-0.5,0.5),(-2,2)] # 每个参数的值间隔
nbins = [20,20,10,10] # 每个参数的 bin 数量
bins = [create_bins(ints[i],nbins[i]) for i in range(4)]
def discretize_bins(x):
return tuple(np.digitize(x[i],bins[i]) for i in range(4))
```
3. 现在让我们运行一个简短的模拟并观察那些离散的环境值。随意尝试 `discretize``discretize_bins` ,看看是否有区别。
✅ discretize_bins 返回 bin 编号,从 0 开始。因此对于0附近 的输入变量值,它返回区间 (10) 中间的数字。在离散化中我们不关心输出值的范围允许它们为负因此状态值不会移位0 对应于 0。代码块 8
```python
env.reset()
done = False
while not done:
#env.render()
obs, rew, done, info = env.step(env.action_space.sample())
#print(discretize_bins(obs))
print(discretize(obs))
env.close()
```
✅ 如果你想查看环境如何执行,请取消以 env.render 开头行的注释。或者你可以在后台执行它,这样会更快。我们将在 Q-Learning 过程中使用这种"隐形"执行。
## Q-Table 结构
在我们上一课中,状态是从 0 到 8 的一对简单数字,因此用形状为 8x8x2 的 numpy 张量来表示 Q-Table 很方便。如果我们使用 bins 离散化,我们的状态向量的大小也是已知的,所以我们可以使用相同的方法,用一个形状为 20x20x10x10x2 的数组来表示状态(这里 2 是动作空间的维度,第一个维度对应于我们选择用于观察空间中的每个参数的箱)。
然而,有时不知道观察空间的精确尺寸。在 `discretize` 函数的情况下,我们可能永远无法确定我们的状态是否保持在某些限制内,因为一些原始值不受约束。因此,我们将使用稍微不同的方法并用字典表示 Q-Table。
1. 使用 *(state,action)* 对作为字典键,该值将对应于 Q-Table 条目值。(代码块 9
```python
Q = {}
actions = (0,1)
def qvalues(state):
return [Q.get((state,a),0) for a in actions]
```
这里我们还定义了一个函数 `qvalues()`,它返回对应于所有可能操作的给定状态的 Q-Table 值列表。如果该条目不存在于 Q-Table 中,我们将返回 0 作为默认值。
## 让我们开始 Q-Learning
现在我们准备教彼得平衡!
1. 首先,让我们设置一些超参数:(代码块 10
```python
# hyperparameters
alpha = 0.3
gamma = 0.9
epsilon = 0.90
```
这里,`alpha` 是**学习率**,它定义了我们应该在每一步调整 Q-Table 的当前值的程度。在上一课中,我们从 1 开始,然后在训练期间将 `alpha` 减小到较低的值。在这个例子中,为了简单起见,我们将保持它不变,你可以稍后尝试调整 `alpha` 值。
`gamma` 是**折扣因素**,它表明我们应该在多大程度上优先考虑未来的奖励而不是当前的奖励。
`epsilon` 是**探索/开发因素**,它决定了我们是否应该更喜欢探索而不是开发,反之亦然。在我们的算法中,我们将在 `epsilon` 百分比的情况下根据 Q-Table 值选择下一个动作,在剩余的情况下,我们将执行随机动作。这将使我们能够探索我们以前从未见过的搜索空间区域。
✅ 在平衡方面 - 选择随机动作(探索)将作为朝着错误方向的随机一拳,杆子必须学习如何从这些"错误"中恢复平衡
### 改进算法
我们还可以对上一课的算法进行两项改进:
- **计算平均累积奖励**,经过多次模拟。我们每 5000 次迭代打印一次进度,并计算这段时间内累积奖励的平均值。这意味着如果我们得到超过 195 分——我们可以认为问题已经解决,甚至比要求的质量更高。
- **计算最大平均累积结果**`Qmax`我们将存储与该结果对应的Q-Table。当你运行训练时你会注意到有时平均累积结果开始下降我们希望保留与训练期间观察到的最佳模型相对应的 Q-Table 值。
1. 在 `rewards` 向量处收集每次模拟的所有累积奖励,用于进一步绘图。(代码块 11
```python
def probs(v,eps=1e-4):
v = vv.min()+eps
v = v/v.sum()
return v
Qmax = 0
cum_rewards = []
rewards = []
for epoch in range(100000):
obs = env.reset()
done = False
cum_reward=0
# == do the simulation ==
while not done:
s = discretize(obs)
if random.random()<epsilon:
# exploitation - chose the action according to Q-Table probabilities
v = probs(np.array(qvalues(s)))
a = random.choices(actions,weights=v)[0]
else:
# exploration - randomly chose the action
a = np.random.randint(env.action_space.n)
obs, rew, done, info = env.step(a)
cum_reward+=rew
ns = discretize(obs)
Q[(s,a)] = (1 - alpha) * Q.get((s,a),0) + alpha * (rew + gamma * max(qvalues(ns)))
cum_rewards.append(cum_reward)
rewards.append(cum_reward)
# == Periodically print results and calculate average reward ==
if epoch%5000==0:
print(f"{epoch}: {np.average(cum_rewards)}, alpha={alpha}, epsilon={epsilon}")
if np.average(cum_rewards) > Qmax:
Qmax = np.average(cum_rewards)
Qbest = Q
cum_rewards=[]
```
你可能会从这些结果中注意到:
- **接近我们的目标**。我们非常接近实现在连续 100 多次模拟运行中获得 195 个累积奖励的目标,或者我们可能真的实现了!即使我们得到更小的数字,我们仍然不知道,因为我们平均超过 5000 次运行,而在正式标准中只需要 100 次运行。
- **奖励开始下降**。有时奖励开始下降,这意味着我们可以"破坏" Q-Table 中已经学习到的值,这些值会使情况变得更糟。
如果我们绘制训练进度图,则这种观察会更加清晰可见。
## 绘制训练进度
在训练期间,我们将每次迭代的累积奖励值收集到`rewards`向量中。以下是我们根据迭代次数绘制它时的样子:
```python
plt.plot(reawrd)
```
![原始进度](../images/train_progress_raw.png)
从这张图中,无法说明任何事情,因为由于随机训练过程的性​​质,训练课程的长度差异很大。为了更好地理解这个图,我们可以计算一系列实验的 **running average**,假设为 100。这可以使用 `np.convolve` 方便地完成:(代码块 12
```python
def running_average(x,window):
return np.convolve(x,np.ones(window)/window,mode='valid')
plt.plot(running_average(rewards,100))
```
![训练进度](../images/train_progress_runav.png)
## 不同的超参数
为了让学习更稳定,在训练期间调整我们的一些超参数是有意义的。特别是:
- **对于学习率**`alpha`,我们可以从接近 1 的值开始,然后不断减小参数。随着时间的推移,我们将在 Q-Table 中获得良好的概率值,因此我们应该稍微调整它们,而不是用新值完全覆盖。
- **增加epsilon**。我们可能希望缓慢增加`epsilon`,以便探索更少,开发更多。从`epsilon`的较低值开始,然后上升到接近 1 可能是有意义的。
> **任务 1**玩转超参数值看看是否可以获得更高的累积奖励。你超过195了吗
> **任务 2**:要正式解决问题,你需要在 100 次连续运行中获得 195 的平均奖励。在培训期间衡量并确保你已经正式解决了问题!
## 在行动中看到结果
实际看看受过训练的模型的行为会很有趣。让我们运行模拟并遵循与训练期间相同的动作选择策略,根据 Q-Table 中的概率分布进行采样:(代码块 13
```python
obs = env.reset()
done = False
while not done:
s = discretize(obs)
env.render()
v = probs(np.array(qvalues(s)))
a = random.choices(actions,weights=v)[0]
obs,_,done,_ = env.step(a)
env.close()
```
你应该会看到如下内容:
![平衡车杆](../images/cartpole-balance.gif)
---
## 🚀挑战
> **任务 3**:在这里,我们使用的是 Q-Table 的最终副本,它可能不是最好的。请记住,我们已将性能最佳的 Q-Table 存储到 `Qbest` 变量中!通过将`Qbest`复制到`Q`来尝试使用性能最佳的 Q-Table 的相同示例,看看你是否注意到差异。
> **任务 4**:这里我们不是在每一步选择最佳动作,而是用相应的概率分布进行采样。始终选择具有最高 Q-Table 值的最佳动作是否更有意义?这可以通过使用 `np.argmax` 函数找出对应于较高 Q-Table 值的动作编号来完成。实施这个策略,看看它是否能改善平衡。
## [课后测验](https://white-water-09ec41f0f.azurestaticapps.net/quiz/48/)
## 作业:[训练山地车](assignment.zh-cn.md)
## 结论
我们现在已经学会了如何训练智能体以取得良好的结果,只需为它们提供一个定义游戏所需状态的奖励函数,并为它们提供智能探索搜索空间的机会。我们已经成功地将 Q-Learning 算法应用于离散和连续环境的情况,但具有离散动作。
研究动作状态也是连续的情况以及观察空间复杂得多的情况也很重要,例如来自 Atari 游戏屏幕的图像。在那些问题中,我们往往需要使用更强大的机器学习技术,比如神经网络,才能取得好的效果。这些更高级的主题在我们即将推出的更高级 AI 课程的主题中。

@ -0,0 +1,47 @@
# 连续山地车
[OpenAI Gym](http://gym.openai.com) 的设计方式是所有环境都提供相同的 API - 即相同的方法 `reset`、`step` 和 `render`,以及相同的抽象**动作空间**和**观察空间**。因此,应该可以通过最少的代码更改使相同的强化学习算法适应不同的环境。
## 山地车环境
[山地车环境](https://gym.openai.com/envs/MountainCar-v0/) 包含一辆卡在山谷中的汽车:
<img src="../images/mountaincar.png" width="300"/>
目标是通过在每一步执行以下任一操作来走出山谷并得到旗帜:
| 值 | 含义 |
|---|---|
| 0 | 向左加速 |
| 1 | 不加速|
| 2 | 向右加速|
然而,这个问题的主要技巧是,汽车的引擎不够强大,无法一次性翻越这座山。因此,成功的唯一方法是来回驱动以积聚动力。
观察空间仅包含两个值:
| 数量 | 观察 | 最小 | 最大 |
|-----|--------------|-----|-----|
| 0 | 车位置 | -1.2| 0.6 |
| 1 | 车速度 | -0.07 | 0.07 |
山地车的奖励系统相当棘手:
- 如果山地车到达山顶的标志(位置 = 0.5)则奖励 0。
- 如果代理的位置小于 0.5,则奖励 -1。
如果汽车位置大于 0.5 或步骤长度大于 200则游戏终止。
## 说明
调整我们的强化学习算法来解决山地车问题。从现有的 [notebook.ipynb](../notebook.ipynb)代码开始,替换新环境,更改状态离散化函数,并尝试使现有算法以最少的代码修改进行训练。通过调整超参数来优化结果。
> 注意:可能需要调整超参数以使算法收敛。
## 评判标准
| 标准 | 优秀 | 中规中矩 | 仍需努力 |
| -------- | --------- | -------- | ----------------- |
| | Q-Learning 算法成功地改编自 CartPole 示例,代码修改最少,能够解决 200 步以下得到旗帜的问题。 | 一种新的 Q-Learning 算法已从 Internet 上采用,但有据可查;或采用现有算法,但未达到预期效果 | 学生无法成功采用任何算法但已经迈出了解决问题的实质性步骤实现了状态离散化、Q-Table 数据结构等)|

@ -0,0 +1,13 @@
# Posfácio: Aplicações no mundo real do Machine Learning clássico
Nesta seção do currículo, você será apresentado a algumas aplicações do ML clássico. Ao vasculhar publicações e artigos sobre essas aplicações na internet, nós buscamos trazer apenas a ML de modo a evitar, ao máximo, usar as estratégias de redes neurais, deep learning e IA. Aprenda sobre como o ML é usado nos sistemas de negócios, nas aplicações ecológicas, nas finanças, na arte, na cultura e muito mais.
![xadrez](../images/chess.jpg)
> Foto de <a href="https://unsplash.com/@childeye?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Alexis Fauvet</a> disponível em <a href="https://unsplash.com/s/photos/artificial-intelligence?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## Aula
1. [Aplicações práticas do ML no mundo real](https://github.com/microsoft/ML-For-Beginners/blob/main/9-Real-World/1-Applications/README.md)
## Créditos
"Real-World Applications" foi escrito por uma equipe de colegas, dentre eles [Jen Looper](https://twitter.com/jenlooper) e [Ornella Altunyan](https://twitter.com/ornelladotcom).

@ -16,7 +16,7 @@ Azure Cloud Advocates at Microsoft are pleased to offer a 12-week, 24-lesson (pl
Travel with us around the world as we apply these classic techniques to data from many areas of the world. Each lesson includes pre- and post-lesson quizzes, written instructions to complete the lesson, a solution, an assignment and more. Our project-based pedagogy allows you to learn while building, a proven way for new skills to 'stick'.
**✍️ Hearty thanks to our authors** Jen Looper, Stephen Howell, Francesca Lazzeri, Tomomi Imura, Cassie Breviu, Dmitry Soshnikov, Chris Noring, Ornella Altunyan, and Amy Boyd
**✍️ Hearty thanks to our authors** Jen Looper, Stephen Howell, Francesca Lazzeri, Tomomi Imura, Cassie Breviu, Dmitry Soshnikov, Chris Noring, Anirban Mukherjee, Ornella Altunyan, and Amy Boyd
**🎨 Thanks as well to our illustrators** Tomomi Imura, Dasani Madipalli, and Jen Looper
@ -101,8 +101,9 @@ By ensuring that the content aligns with projects, the process is made more enga
| 20 | Romantic hotels of Europe ♥️ | [Natural language processing](6-NLP/README.md) | Sentiment analysis with hotel reviews 2 | [Python](6-NLP/5-Hotel-Reviews-2/README.md) | Stephen |
| 21 | Introduction to time series forecasting | [Time series](7-TimeSeries/README.md) | Introduction to time series forecasting | [Python](7-TimeSeries/1-Introduction/README.md) | Francesca |
| 22 | ⚡️ World Power Usage ⚡️ - time series forecasting with ARIMA | [Time series](7-TimeSeries/README.md) | Time series forecasting with ARIMA | [Python](7-TimeSeries/2-ARIMA/README.md) | Francesca |
| 23 | Introduction to reinforcement learning | [Reinforcement learning](8-Reinforcement/README.md) | Introduction to reinforcement learning with Q-Learning | [Python](8-Reinforcement/1-QLearning/README.md) | Dmitry |
| 24 | Help Peter avoid the wolf! 🐺 | [Reinforcement learning](8-Reinforcement/README.md) | Reinforcement learning Gym | [Python](8-Reinforcement/2-Gym/README.md) | Dmitry |
| 23 | ⚡️ World Power Usage ⚡️ - time series forecasting with SVR | [Time series](7-TimeSeries/README.md) | Time series forecasting with Support Vector Regressor | [Python](7-TimeSeries/3-SVR/README.md) | Anirban |
| 24 | Introduction to reinforcement learning | [Reinforcement learning](8-Reinforcement/README.md) | Introduction to reinforcement learning with Q-Learning | [Python](8-Reinforcement/1-QLearning/README.md) | Dmitry |
| 25 | Help Peter avoid the wolf! 🐺 | [Reinforcement learning](8-Reinforcement/README.md) | Reinforcement learning Gym | [Python](8-Reinforcement/2-Gym/README.md) | Dmitry |
| Postscript | Real-World ML scenarios and applications | [ML in the Wild](9-Real-World/README.md) | Interesting and revealing real-world applications of classical ML | [Lesson](9-Real-World/1-Applications/README.md) | Team |
## Offline access

@ -33,6 +33,7 @@
- Time Series Forecasting
- [Introduction to Time Series Forecasting](../7-TimeSeries/1-Introduction/README.md)
- [ARIMA](../7-TimeSeries/2-ARIMA/README.md)
- [SVR](../7-TimeSeries/3-SVR/README.md)
- Reinforcement Learning
- [Q-Learning](../8-Reinforcement/1-QLearning/README.md)

Binary file not shown.

@ -1710,15 +1710,6 @@
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"cacache": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz",
@ -1745,48 +1736,6 @@
"unique-filename": "^1.1.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@ -1803,15 +1752,6 @@
"minipass": "^3.1.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"terser-webpack-plugin": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz",
@ -1828,17 +1768,6 @@
"terser": "^4.6.12",
"webpack-sources": "^1.4.3"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.1",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.1.tgz",
"integrity": "sha512-V53TJbHmzjBhCG5OYI2JWy/aYDspz4oVHKxS43Iy212GjGIG1T3EsB3+GWXFm/1z5VwjdjLmdZUFYM70y77vtQ==",
"dev": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
}
}
},
@ -3004,9 +2933,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001170",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz",
"integrity": "sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==",
"version": "1.0.30001265",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz",
"integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==",
"dev": true
},
"case-sensitive-paths-webpack-plugin": {
@ -3692,9 +3621,9 @@
}
},
"core-js": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg=="
"version": "3.18.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.2.tgz",
"integrity": "sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ=="
},
"core-js-compat": {
"version": "3.8.1",
@ -10952,9 +10881,9 @@
"dev": true
},
"vue": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
"version": "2.6.14",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
},
"vue-eslint-parser": {
"version": "7.3.0",
@ -10989,9 +10918,9 @@
"dev": true
},
"vue-i18n": {
"version": "8.22.2",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.22.2.tgz",
"integrity": "sha512-rb569fVJInPUgS/bbCxEQ9DrAoFTntuJvYoK4Fpk2VfNbA09WzdTKk57ppjz3S+ps9hW+p9H+2ASgMvojedkow=="
"version": "8.26.1",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.26.1.tgz",
"integrity": "sha512-N6GpogueNQqmAye6lkUySlrXAZqBs9DYz8+8LHxm4IV7hEP/KWQL9VUCV8oJ0DS1asUTlvI2qKm2MydRgoPJFQ=="
},
"vue-loader": {
"version": "15.9.6",
@ -11014,10 +10943,91 @@
}
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.1",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.1.tgz",
"integrity": "sha512-V53TJbHmzjBhCG5OYI2JWy/aYDspz4oVHKxS43Iy212GjGIG1T3EsB3+GWXFm/1z5VwjdjLmdZUFYM70y77vtQ==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-router": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz",
"integrity": "sha512-CGAKWN44RqXW06oC+u4mPgHLQQi2t6vLD/JbGRDAXm0YpMv0bgpKuU5bBd7AvMgfTz9kXVRIWKHqRwGEb8xFkA=="
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.2.tgz",
"integrity": "sha512-807gn82hTnjCYGrnF3eNmIw/dk7/GE4B5h69BlyCK9KHASwSloD1Sjcn06zg9fVG4fYH2DrsNBZkpLtb25WtaQ=="
},
"vue-style-loader": {
"version": "4.1.2",

@ -2809,6 +2809,120 @@
]
}
]
},
{
"id": 51,
"title": "Time Series SVR: Pre-Lecture Quiz",
"quiz": [
{
"questionText": "SVM stands for",
"answerOptions": [
{
"answerText": "Statistical Vector Machine",
"isCorrect": "false"
},
{
"answerText": "Support Vector Machine",
"isCorrect": "true"
},
{
"answerText": "Statistical Vector Model",
"isCorrect": "false"
}
]
},
{
"questionText": "Which of these ML techniques is used to predict continuous values?",
"answerOptions": [
{
"answerText": "Clustering",
"isCorrect": "false"
},
{
"answerText": "Classification",
"isCorrect": "false"
},
{
"answerText": "Regression",
"isCorrect": "true"
}
]
},
{
"questionText": "Which of these models is popularly used for time series forecasting?",
"answerOptions": [
{
"answerText": "ARIMA",
"isCorrect": "true"
},
{
"answerText": "K-Means Clustering",
"isCorrect": "false"
},
{
"answerText": "Logistic Regression",
"isCorrect": "false"
}
]
}
]
},
{
"id": 52,
"title": "Time Series SVR: Post-Lecture Quiz",
"quiz": [
{
"questionText": "By which of these methods does an SVR learn?",
"answerOptions": [
{
"answerText": "Finding the best fit hyperplane that has the maximum number of data points",
"isCorrect": "true"
},
{
"answerText": "Learning the probability distribution of the dataset",
"isCorrect": "false"
},
{
"answerText": "Finding clusters in the dataset",
"isCorrect": "false"
}
]
},
{
"questionText": "What is the purpose of a kernel in SVMs?",
"answerOptions": [
{
"answerText": "To measure the accuracy of the model predictions",
"isCorrect": "false"
},
{
"answerText": "To transform the dataset to a higher dimension space",
"isCorrect": "true"
},
{
"answerText": "To standardize the values of the dataset",
"isCorrect": "false"
}
]
},
{
"questionText": "Which of these models consider the non-linearity in the dataset?",
"answerOptions": [
{
"answerText": "Simple Linear Regression",
"isCorrect": "false"
},
{
"answerText": "ARIMA",
"isCorrect": "false"
},
{
"answerText": "SVR using RBF kernel",
"isCorrect": "true"
}
]
}
]
}
]
}

Loading…
Cancel
Save