Title
Introdução
Existe uma lenda que corre entre os matemáticos desde o século 13. Ela que chegou à nossa língua por meio do livro: O Homem que Calculava, de 1937.
O autor é: Malba Tahan, um pseudônimo do engenheiro carioca: Júlio Cesar de Mello e Souza (1895-1974).
Conta-se que o rei da província de Telengana, no sul da Índia, não estava bem. Tinha acabado de perder um filho no campo de batalha e agora passava seus dias remoendo a tristeza.
As notícias sobre a depressão do monarca espalharam-se pelo reino. Um jovem, então, foi ao palácio e pediu uma audiência.
Dizia ser Lahur Sessa e que acabara de Invententar um jogo, que poderia trazer novas alegrias ao rei.
Ele trazia um tabuleiro quadrado, dividido em 64 casas. Mais 32 peças, representando soldados, cavalaria, torres de defesa. Ente outros. Era um protótipode 'Chaturanga' (Que deu origem ao nosso atual 'Xadrez').
Ele então viu, jogou e adorou. Ficou tão contente que ofereceu o que ele quisesse como recompensa: ouro, terras ou um palácio. Deu sua palavra. Não importando a quantidade.
O jovem disse que não lhe interessava nenhum desses luxos. Bastavam-lhe grãos de trigo.
O soberano riu com soberba e logo aceitou. Foi então que o inventor revelou: Que deveria preencher cada casa do tabuleiro com o dobro da quantidade de grãos da anteriormente preenchida, até que todas as 64 estivessem completas.
Então, assim se seguiu:
- Casa 1ª, 1 grão de trigo;
- Casa 2ª, 2 grãos de trigo;
- Casa 3ª, 4 grãos de trigo;
- Casa 4ª, 8 grãos de trigo;
- ...
- Casa 9ª, 512 grãos;
- ...
- Casa 18ª, 262 mil;
- ...
- Casa 27ª, 134 milhões;
- ...
- Casa 33ª, 8,5 bilhões;
- ...
No quadrado final, a Casa 64ª, fechava-se a conta: 18.446.744.073.709.551.615 grãos de trigo. 18 sextilhões. Podemos arredondar para o número 18 seguido de 21 'zeros'.
Para dar uma ideia do que esse número significa: Estima-se hoje que o número de grãos de areia na Terra seja de 18 quintilhões. Ou 18 seguido de 18 'zeros'.
Sem perceber, o monarcarca arcou com uma dívida infundada. Impossível de ser paga. Pois era o equivalente a todos os grãos de areia de mil planetas Terra.
Algo mundano como um tabuleiro de 64 casas pode carregar dentro de si um número que, para os nossos cérebros, é indiscernível do infinito.
É uma história que ensina sobre investimento. Sobre atribuir valor. Arcar com escolhas e sobre arrependimento. A somatória das pequenas coisas podendo afetar o todo.
Todos querem lucras como o inventor da história.
Ninguém quer pagar a soma do monarca.
Sobre este notebook
Portanto, um tabuleiro que ajudasse a atribuir preços justos, afim de que não mais se vangloriem os inventores ou saiam derrotados os monarcas, poderia ajudar aqueles que buscam obter, negociar ou arrendar seus bens. Entre o cenário todos os tipos possíveis, mais comum: Um imóvel.
Seria possível criar uma máquina que me entregue o valor justo, competitivo ou atraente de um imóvel por meio dos dados diponíveis?
Para tal, foi desenvolvido este notebook. Ele parte do zero, para um sistema que procesa as informações e entrega a classificação.
Ele foi separado em diferentes estágios até sua função plena:
- Raspagem de dados
- Manipulação dos dados
- Modelagem
- Otimização
- Salvando
- Deploy
Abaixo uma lista de todos os módulos usados para este projeto:
"""
click==8.0.3
Flask==2.0.3
gunicorn==20.1.0
importlib-metadata==4.11.1
itsdangerous==2.0.1
Jinja2==3.0.3
joblib==1.1.0
MarkupSafe==2.0.1
numpy==1.21.5
pandas==1.3.5
python-dateutil==2.8.2
pytz==2021.3
scikit-learn==1.0.2
scipy==1.7.3
six==1.16.0
sklearn==0.0
threadpoolctl==3.1.0
typing-extensions==4.1.1
Werkzeug==2.0.3
zipp==3.7.0
"""
Aqui usaremos a biblioteca 'Selenium' para realizar a obtenção dos dados. Por meio disso será possível acessar o site e obter informações contidas em campos do 'html' contidos em sua estrutura, visível nas ferramentas para o desenvolvedor e armazena-los em variáveis que serão usadas mais à frente.
# Importando Pandas:
from time import sleep
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options
# Definindo url a ser usada:
url = 'https://www.zapimoveis.com.br/aluguel/imoveis/rj+rio-de-janeiro/?gclid=EAIaIQobChMIr87tpubZ9QIVDwuRCh2R_QFZEAAYAyAAEgLqgPD_BwE&utm_referrer=https%3A%2F%2Fwww.google.com%2F'
# Entrando na página:
driver = webdriver.Chrome(executable_path='chromedriver')
driver.get(url)
# Esperar o carregamento da página:
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "simple-card__price"))
)
except TimeoutException:
print('O carregamento da página demorou muito tempo')
cards = driver.find_elements_by_class_name('card-container')
# criar um dataframe:
df = pd.DataFrame(columns=[
'preco',
'condominio',
'endereço',
'area',
'quartos',
'vagas',
'banheiros'
]
)
df = pd.DataFrame(columns=[
'preco',
'condominio',
'endereço',
'area',
'quartos',
'vagas',
'banheiros'
]
)
len_df = len(df)
i = 0
while len_df < 10000:
# scroll down:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
sleep(1)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
sleep(1)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# pegar a lista de cards:
cards = driver.find_elements_by_class_name('card-container')
for card in cards:
# search for itemprop="floorSize" in card[1]:
try:
floor_size = card.find_elements_by_class_name('js-areas')[0].text
except:
break
try:
bedrooms = card.find_elements_by_class_name('js-bedrooms')[0].text
except Exception:
bedrooms = 0
try:
parking_spaces = card.find_elements_by_class_name('js-parking-spaces')[0].text
except Exception:
parking_spaces = 0
try:
bathrooms = card.find_elements_by_class_name('js-bathrooms')[0].text
except Exception:
bathrooms = 0
price = card.find_element_by_class_name('simple-card__price').text
try:
condominio = card.find_element_by_class_name('card-price__value').text
except Exception:
condominio = 0
address = card.find_element_by_class_name('simple-card__address').text
# print('price:', price, 'condominio:', condominio, 'address:', address)
# print('floor_size:', floor_size, 'bedrooms:', bedrooms, 'parking_spaces:', parking_spaces, 'bathrooms:', bathrooms)
# adicionar os dados ao dataframe:
df = df.append({
'preco': price,
'condominio': condominio,
'endereço': address,
'area': floor_size,
'quartos': bedrooms,
'vagas': parking_spaces,
'banheiros': bathrooms
}, ignore_index=True)
len_df = len(df)
print('len_df:', len_df, '/10000')
# display(df)
sleep(3)
# click in button with class pagination__button--next
url = f'https://www.zapimoveis.com.br/aluguel/imoveis/rj+rio-de-janeiro/?pagina={(i+2)}&onde=,Rio%20de%20Janeiro,Rio%20de%20Janeiro,,,,,CITY,BR%3ERio%20de%20Janeiro%3ENULL%3ERio%20de%20Janeiro,-22.906847,-43.172897&transacao=Aluguel&tipo=Im%C3%B3vel%20usado'
driver.get(url)
i += 1
sleep(3)
df.drop_duplicates(keep='first', inplace=True)
df.to_csv('lista_de_alugueis.csv', index=False)
import pandas as pd
df = pd.read_csv('lista_de_alugueis.csv')
df.head(15)
df['preco'] = df['preco'].str.replace(r'[^0-9]', '')
df['condominio'] = df['condominio'].str.replace(r'[^0-9]', '')
df['area'] = df['area'].str.replace(r'[^0-9]', '')
df.head(1)
df['preco_total'] = pd.to_numeric(df['preco']) + pd.to_numeric(df['condominio'])
df.head(5)
for index, row in df.iterrows():
if ', Rio de Janeiro' in row['endereço']:
df.loc[index, 'endereço'] = row['endereço'].replace(', Rio de Janeiro', '')
else:
df.loc[index, 'endereço'] = row['endereço'].split(',')[1]
df.head(5)
df['bairro'] = df['endereço']
df.drop('endereço', axis=1, inplace=True)
# remove all ' ' from 'bairro' column:
df['bairro'] = df['bairro'].str.replace(' ', '')
df.head(1)
df.rename(columns={'preco_total': 'aluguel'}, inplace=True)
df = df[['aluguel', 'bairro', 'area', 'quartos', 'vagas', 'banheiros']]
dummies = pd.get_dummies(df, columns=['bairro'], drop_first=False, sparse=True)
dummies = pd.concat([df['bairro'], dummies], axis=1)
dummies
dummies.to_csv('lista_de_alugueis_processada.csv', index=False)
import pandas as pd
import numpy as nd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# import sklearn logistic regression
from sklearn.linear_model import LogisticRegression
# import sklearn k-nearst neighbors
from sklearn.neighbors import KNeighborsClassifier
# import sklearn support vector machine
from sklearn.svm import SVC
# import sklearn naive bayes
from sklearn.naive_bayes import GaussianNB
# import sklearn decision tree
from sklearn.tree import DecisionTreeClassifier
# import sklearn random forest
from sklearn.ensemble import RandomForestClassifier
alugueis = pd.read_csv('lista_de_alugueis_processada.csv')
alugueis.head(5)
alugueis.shape
alugueis.isnull().sum()
def var_summary(x):
return pd.Series([x.count(), x.isnull().sum(), x.sum(), x.mean(), x.median(), x.std(), x.var(), x.min(), x.dropna().quantile(0.01), x.dropna().quantile(0.05),x.dropna().quantile(0.10),x.dropna().quantile(0.25),x.dropna().quantile(0.50),x.dropna().quantile(0.75), x.dropna().quantile(0.90),x.dropna().quantile(0.95), x.dropna().quantile(0.99),x.max()],
index=['N', 'NMISS', 'SUM', 'MEAN','MEDIAN', 'STD', 'VAR', 'MIN', 'P1' , 'P5' ,'P10' ,'P25' ,'P50' ,'P75' ,'P90' ,'P95' ,'P99' ,'MAX'])
numerical_features = ['aluguel', 'area', 'quartos', 'vagas', 'banheiros']
alugueis[numerical_features].apply(lambda x: var_summary(x)).T
alugueis.dtypes
categorical_features = ['bairro']
numerical_features = ['area', 'quartos', 'banheiros', 'vagas', 'aluguel']
sns.set_style('whitegrid')
# plot one histogram for each numerical feature
for feature in numerical_features:
sns.distplot(alugueis[feature], hist=False, label=feature)
plt.show()
bairros = []
for feature in categorical_features:
bairros.append([feature, alugueis[feature].sum()])
# order list by bairros[1] in descending order
bairros.sort(key=lambda x: x[1], reverse=True)
bairros
avg_rents = alugueis.groupby('bairro').mean().reset_index()[['bairro', 'aluguel']]
avg_rents['aluguel'] = [round(r) for r in avg_rents.aluguel]
avg_rents.sort_values(by=['aluguel'], ascending=False, inplace=True)
# plot boxplot for each bairro
sns.barplot(x='bairro', y='aluguel', data=avg_rents.head(15))
# rotate x-axis labels
plt.xticks(rotation=90)
plt.show()
Os preço medio em bairros acima como Guadalupe, Pavuna e Santo Cristo se justificam por terem muitos imóveis inteiros em aluguel, como galpões e prédios.
corr = alugueis[numerical_features].corr()
plt.figure(figsize=(6,6))
sns.heatmap(corr, cmap='RdBu_r', annot=True, vmax=1, vmin=-1)
plt.show()
fatores como area, banheiro e vagas aparentam ter um efeito maior no preço do aluguel. Porém sem dúvida o bairro do imóvel também tem um peso. Fiquei curioso em entender como o numero de quartos não se correlaciona com o preço, e irei plotar um gráfico para verificar:
sns.lmplot(x='quartos', y='aluguel', data=alugueis)
plt.show()
Os galpões parecem de alguma maneira afetar essa variável, penso em remover os imóveis que não possuem nenhum quarto de nossa análise, abaixo considerarei essa opção
alugueis_modificada = alugueis[alugueis.quartos != 0]
alugueis_modificada[numerical_features].apply(lambda x: var_summary(x)).T
sns.lmplot(x='quartos', y='aluguel', data=alugueis_modificada)
plt.show()
corr = alugueis_modificada[numerical_features].corr()
plt.figure(figsize=(6,6))
sns.heatmap(corr, cmap='RdBu_r', annot=True, vmax=1, vmin=-1)
plt.show()
Como a matriz de correlação aparenta fazer um pouco mais de sentido, criarei o modelo com base em alugueis_modificada
train_set, test_set = train_test_split(alugueis, test_size=0.2, random_state=1)
features = train_set.drop(['bairro'], axis=1).columns.tolist()
# add all models imported above
models = [
LogisticRegression(),
KNeighborsClassifier(),
SVC(),
GaussianNB(),
DecisionTreeClassifier(),
RandomForestClassifier()
]
# create a list of model names
model_names = [
'Logistic Regression',
'K-Nearest Neighbors',
'Support Vector Machine',
'Naive Bayes',
'Decision Tree',
'Random Forest'
]
# create a dataframe to store the results
results = pd.DataFrame(columns=['Model', 'Score'])
# loop through the models
for model, name in zip(models, model_names):
# train the model
model.fit(train_set[features], train_set['aluguel'])
# make predictions
predictions = model.predict(test_set[features])
# calculate the score
score = model.score(test_set[features], test_set['aluguel'])
# store the results
results = results.append({'Model': name, 'Score': score}, ignore_index=True)
results
from sklearn.model_selection import GridSearchCV
# hyperparameter tuning for decision tree classifier:
# create a list of hyperparameters
hyperparameters = {
'min_samples_leaf': [1, 2, 4, 8, 16, 32, 64],
'min_samples_split': [2, 5, 10, 15, 20],
'criterion': ['gini', 'entropy'],
'max_features': [None, "auto", "sqrt", "log2"],
'class_weight': [None, 'balanced']
}
def decision_tree_classifier(hyperparameters):
# create a decision tree classifier
clf = DecisionTreeClassifier()
# create a grid search object
gs = GridSearchCV(clf, hyperparameters, cv=5, n_jobs=-1)
# fit the data
gs.fit(train_set[features], train_set['aluguel'])
# return the grid search object
return gs
# get results:
gs = decision_tree_classifier(hyperparameters)
print('Best Score is ',gs.best_score_)
print(gs.best_params_, 'are the params')
def var_summary(x):
return pd.Series([x.count(), x.isnull().sum(), x.sum(), x.mean(), x.median(), x.std(), x.var(), x.min(), x.dropna().quantile(0.01), x.dropna().quantile(0.05),x.dropna().quantile(0.10),x.dropna().quantile(0.25),x.dropna().quantile(0.50),x.dropna().quantile(0.75), x.dropna().quantile(0.90),x.dropna().quantile(0.95), x.dropna().quantile(0.99),x.max()],
index=['N', 'NMISS', 'SUM', 'MEAN','MEDIAN', 'STD', 'VAR', 'MIN', 'P1' , 'P5' ,'P10' ,'P25' ,'P50' ,'P75' ,'P90' ,'P95' ,'P99' ,'MAX'])
# see the list of predictions in comparison with the test set
predictions = gs.predict(test_set[features])
# create a dataframe to compare predictions with 'aluguel'
compare = pd.DataFrame(test_set['aluguel'])
compare['predictions'] = predictions
compare['error'] = compare['aluguel'] - compare['predictions']
compare['percent_error'] = ((compare['error'] / compare['aluguel'] ) * 100)
compare.apply(lambda x: var_summary(x)).T
A media do erro na previsão é de 0,07%, com desvio padrão de 4.5 pontos percentuais, o que sifnifica que em 95% das previsões o valor do aluguel tem uma diferença de menos de 1% para o valor real de um apartamento nas condições apresentadas
from sklearn import model_selection, datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split
import pickle
import pandas as pd
alugueis = pd.read_csv('lista_de_alugueis_processada.csv')
alugueis.head(5)
train_set, test_set = train_test_split(alugueis, test_size=0.2, random_state=1)
features = train_set.drop(['bairro'], axis=1).columns.tolist()
features_list = pd.DataFrame(features)
features_list.to_csv('features_list.csv', index=False)
model = RandomForestClassifier(n_estimators=198, min_samples_split=2, min_samples_leaf=1, max_features='sqrt', max_depth=11, bootstrap=True)
model.fit(train_set[features].drop(['aluguel'], axis=1), train_set['aluguel'])
filename = "calculadora-de-aluguel-model.joblib"
joblib.dump(model, filename)
imovel = test_set[ ['bairro'] + features].head(10)
imovel
filename = "calculadora-de-aluguel-model.joblib"
loaded_model = joblib.load(filename)
result = loaded_model.predict(test_set[features].drop(['aluguel'], axis=1).head(10))
print(result.tolist())
Abaixo se encontra a solução com o passo a passo para final importada para o formato legivel via Heroku.
Esta é uma plataforma em nuvem, como o conceito de platform as a service (PaaS) que suporta várias linguagens de programação. Entre elas o Python.
Para se contruir um modelo igual, é necessário também o cadastro no Git, a fim de realizar o controle de versionamento do seu código. Portanto é necessário antes de implementar o modelo, seguir com sua instalação completamnte.
No terminal do Git, abra a pasta do projeto:
cd \users\desktop\flask{coloque o nome de seu arquivo.py aqui}
Em seguida, digite o código abaixo para fazer login no Heroku:> heroku login Note que depois disso, aparecerá a mensagem abaixo:
heroku:Press any key to open up the browser to login or q to exit: Pressione qualquer tecla para fazer login, em seguida, ele abrirá uma janela, com o site do Heroku para inserir email e senha. Realize seu login aqui. Feito isso, no terminal, você receberá a mensagem abaixo: Opening browser to https://cli-auth.heroku.com/auth/cli/browser/> b166712b-6219-4430-9f61-2ccef9cdbc83 Logging in... done Logged in as youraccount@gmail.com
Agora vamos ativar o ambiente virtual (aqui no caso para Windowns):> venv\Scripts\activate É interessante verificar se todas as bibliotecas necessárias para executar o seu projeto estão instaladas; para isso use o comando abaixo para listar todas elas:
pip freeze
Outro ponto importante é instalar o Gunicorn, ele será usado como nosso servidor WSGI Python:> pip install gunicorn O Heroku precisa conhecer as dependências do nosso aplicativo para que no momento do deploy crie o ambiente corretamente, utilizei o pip freeze apontando para requirements.txt:
pip freeze > requirements.txt
Agora, criaremos o arquivo Procfile, onde será gravado o comando que o Heroku deve usar para executar nosso aplicativo. Basicamente, o mesmo comando que usaríamos para executar o aplicativo localmente. o mesmo deve permanecer na raiz do projeto.
echo "web:gunicorn app:app" > Procfile Agora vamos criar um repositório no diretório atual usando o comando git init: git init
Vamos criar um arquivo chamado .gitignore, nele colocaremos todos os arquivos que não queremos que sejam lidos o seu conteúdo, para o nosso cenário colocaremos apenas nosso ambiente virtual “venv”. Vamos adicionar todos os arquivos ao nosso repositório usando git add:> git add . Agora vamos criar nosso commit inicial:
git commit -m "initial commit"
Agora vamos criar nosso aplicativo no Heroku usando o comando heroku apps:create [app name], neste caso, eu chamo meu aplicativo:> heroku apps:create app name Assim que criada, a mensagem abaixo será impressa:
Creating ⬢ app name... done https://app name.herokuapp.com/ | https://git.heroku.com/app name.git Observe que a URL do API e do repositório git foi retornada na mensagem acima para onde nosso aplicativo foi enviado. Para o deploy nosso aplicativo, basta enviar as confirmações do repositório local para o repositório heroku, usando o comando git push heroku master: git push heroku master
Em seguida, aparece uma mensagem abaixo:remote: Verifying deploy... done.To https://git.heroku.com/app name.git
from sklearn import model_selection, datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split
import pickle
import pandas as pd
alugueis = pd.read_csv('lista_de_alugueis_processada.csv')
# separe os dados em treino e teste
train_set, test_set = train_test_split(alugueis, test_size=0.2, random_state=1)
features = train_set.drop(['bairro'], axis=1).columns.tolist()
# save features list t csv
features_list = pd.DataFrame(features)
features_list.to_csv('features_list.csv', index=False)
#Precisei diminuir max depth de 28 para 11 para que heroku app tenha menos que 1GB de memória
model = RandomForestClassifier(n_estimators=198, min_samples_split=2, min_samples_leaf=1, max_features='sqrt', max_depth=11, bootstrap=True)
model.fit(train_set[features].drop(['aluguel'], axis=1), train_set['aluguel'])
filename = "calculadora-de-aluguel-model.joblib"
joblib.dump(model, filename)
# Prevendo o aluguel de 10 imóveis
imovel = test_set[ ['bairro'] + features].head(10)
imovel
filename = "calculadora-de-aluguel-model.joblib"
loaded_model = joblib.load(filename)
result = loaded_model.predict(test_set[features].drop(['aluguel'], axis=1).head(10))
print(result.tolist())
from curses import pair_content
from flask import Flask, render_template, request
import pandas as pd
from sklearn.externals import joblib
import sys
app = Flask(__name__)
@app.route('/')
def index():
return render_template('calculadora-front-end.html')
@app.route('/calcular', methods=['POST'])
def calcular():
area = request.form['area']
bairro = request.form['bairro']
quartos = request.form['quartos']
vagas = request.form['vagas']
banheiros = request.form['banheiros']
features = pd.read_csv('features_list.csv')['0'].to_list()
payload = pd.DataFrame(columns=features)
# make all the bairro_ values in the payload 0
for feature in features:
if 'bairro_' in feature:
payload.loc[0, f'{feature}'] = 0
payload.loc[0, 'area'] = area
payload.loc[0,'bairro'] = bairro
payload.loc[0,'quartos'] = quartos
payload.loc[0,'vagas'] = vagas
payload.loc[0,'banheiros'] = banheiros
payload.loc[0,f'bairro_{bairro}'] = 1
# passing values to model and getting the prediction
filename = "calculadora-de-aluguel-model.joblib"
loaded_model = joblib.load(filename)
result = loaded_model.predict(payload[features].drop(['aluguel'], axis=1).head(10))
return render_template('aluguel_calculado.html', aluguel=result[0])
if __name__ == '__main__':
app.run(debug=True)
<!-- ####### YAY, I AM THE SOURCE EDITOR! #########-->
<h1 style="color: #5e9ca0;">Calculadora de Aluguel da cidade do Rio de Janeiro</h1>
<h2 style="color: #2e6c80;">Adicione abaixo caracteristicas do apartamento e receba o valor do aluguel!</h2>
<!-- Make all text above in the same color pallete: -->
<h4 style="color: #25405f;">
<form action="{{ url_for('calcular') }}" method="post">
<p><strong>Área (m<sup>2</sup>):</strong></p>
<p><input name="area" type="number" value='65'/></p>
<p><strong>Quartos: </strong></p>
<p><input name="quartos" type="number" value='2'/></p>
<p><strong>Vagas: </strong></p>
<p><input name="vagas" type="number" value='1'/></p>
<p><strong>Banheiros: </strong></p>
<p><input name="banheiros" type="number" value='1'/></p>
<p><strong>Bairro: </strong></p>
<p><input id="bairros" list="bairros-list" name="bairro" type="text" /></p>
<datalist id="bairros-list">
<option value="Abolição">
<option value="Anchieta">
<option value="Andaraí">
<option value="Anil">
<option value="Arpoador">
<option value="Bancários">
<option value="Bangu">
<option value="BarradaTijuca">
<option value="BarrosFilho">
<option value="Benfica">
<option value="BentoRibeiro">
<option value="Bonsucesso">
<option value="Botafogo">
<option value="BrazdePina">
<option value="BrásdePina">
<option value="Cachambi">
<option value="Cacuia">
<option value="Caju">
<option value="Camorim">
<option value="Campinho">
<option value="CampoGrande">
<option value="Cascadura">
<option value="Castelo">
<option value="Catete">
<option value="Catumbi">
<option value="Cavalcânti">
<option value="Centro">
<option value="CidadeNova">
<option value="CoelhoNeto">
<option value="Colégio">
<option value="Copacabana">
<option value="Cordovil">
<option value="CosmeVelho">
<option value="Cosmos">
<option value="Curicica">
<option value="DelCastilho">
<option value="Encantado">
<option value="EngenheiroLeal">
<option value="EngenhoDaRainha">
<option value="EngenhoDeDentro">
<option value="EngenhoNovo">
<option value="Estacio">
<option value="Flamengo">
<option value="Freguesia">
<option value="Freguesia-Jacarepaguá">
<option value="Fátima">
<option value="Gamboa">
<option value="Glória">
<option value="Grajaú">
<option value="Grumari">
<option value="Guadalupe">
<option value="Guaratiba">
<option value="Gávea">
<option value="Higienópolis">
<option value="HonórioGurgel">
<option value="Humaitá">
<option value="IlhadoGovernador">
<option value="Inhaúma">
<option value="Inhoaíba">
<option value="Ipanema">
<option value="Irajá">
<option value="Itanhangá">
<option value="Jacarepaguá">
<option value="Jacaré">
<option value="JardimAmérica">
<option value="JardimBotânico">
<option value="JardimCarioca">
<option value="JardimGuanabara">
<option value="JardimOceanico">
<option value="JardimSulacap">
<option value="Lagoa">
<option value="Lapa">
<option value="Laranjeiras">
<option value="Leblon">
<option value="Leme">
<option value="LinsdeVasconcelos">
<option value="Madureira">
<option value="MagalhãesBastos">
<option value="Manguinhos">
<option value="Maracanã">
<option value="MarechalHermes">
<option value="MariadaGraça">
<option value="Moneró">
<option value="Méier">
<option value="Olaria">
<option value="OswaldoCruz">
<option value="Paciência">
<option value="ParadadeLucas">
<option value="Pavuna">
<option value="Pechincha">
<option value="Penha">
<option value="PenhaCircular">
<option value="Piedade">
<option value="Pilares">
<option value="Pitangueiras">
<option value="Portuguesa">
<option value="PraiadaBandeira">
<option value="PraçaSeca">
<option value="PraçadaBandeira">
<option value="QuintinoBocaiúva">
<option value="Ramos">
<option value="Realengo">
<option value="RecreioDosBandeirantes">
<option value="Riachuelo">
<option value="Ribeira">
<option value="RicardodeAlbuquerque">
<option value="RioComprido">
<option value="Rocha">
<option value="RochaMiranda">
<option value="Sampaio">
<option value="SantaCruz">
<option value="SantaTeresa">
<option value="SantoCristo">
<option value="Santíssimo">
<option value="Saúde">
<option value="SenadorCamará">
<option value="SenadorVasconcelos">
<option value="Sepetiba">
<option value="SãoConrado">
<option value="SãoCristóvão">
<option value="SãoFranciscoXavier">
<option value="Tanque">
<option value="Taquara">
<option value="Tauá">
<option value="Tijuca">
<option value="TodososSantos">
<option value="TomásCoelho">
<option value="Turiaçu">
<option value="Urca">
<option value="VargemGrande">
<option value="VargemPequena">
<option value="VicentedeCarvalho">
<option value="Vidigal">
<option value="VigárioGeral">
<option value="VilaIsabel">
<option value="VilaKosmos">
<option value="VilaValqueire">
<option value="ViladaPenha">
<option value="VistaAlegre">
<option value="ÁguaSanta">
</datalist>
<!--- Adicione botão de calcular, que envia dados acima inseridos para back-end.py -->
<input type="submit" value="Calcular">
</form>
</h3>
</body>
</html>
<!-- set tittle "Aluguel Calculado" -->
<h1 style="color: #5e9ca0;">Calculadora de Aluguel da cidade do Rio de Janeiro</h1>
<!-- Add the value of aluguel who it is in aluguel variable: -->
<h2 style="color: #2e6c80;">Valor do Aluguel: R$ {{ aluguel }},00</h2>
<!-- Add back button: -->
<p><a href="{{ url_for('index') }}">Voltar</a></p>
Portanto, segue aqui o resultado final do projeto: Um aplicativo web que reindeniza o modelo dentro dos parâmetros solicitados.
Conclusão:
- O escalonar de um modelo pode ser feito por via de deploy externo, fazendo uso das bibliotecas não nativas do Python;
- O tamanho da máquina é limitado ao processamento, por isso tamanhos de amostras podem ser testados a fim de descobrir qual seria o mais viável;
- Existem ainda diferentes modelos de deploy a serem explorados, cada um com suas particularidades de desempenho e custo. Cada qual ainda também pode-se também implementar deploy;