Partindo da base municipal presente no link, devemos inseri-la no python e contornar seus NAs:
import numpy as np
import pandas as pd
from sklearn import linear_model, svm
if __name__ == '__main__':
RANDOM_SEED = 7
# Definindo a base de dados
data = pd.read_table("BRAZIL_CITIES.csv", sep=None, engine='python', decimal=',')
data.fillna(0, inplace=True)
Como a base está ordenada pelo tamanho da cidade, devemos reordenar as linhas aleatoriamente para construirmos as bases de treino, validação e teste em frações do range, visto que o tamanho da cidade tente a estar correlacionado com a presença de Uber (Entretanto, para replicabilidade, a base usada nessa resposta foi salva e está presente nesse link), conforme código abaixo:
# Aplicando randomização nas linhas da base de dados
data = data.sample(frac=1).reset_index(drop=True)
datam = data.as_matrix()
Para aplicarmos modelos de Machine Learning, devemos definir a variável dependente e as variáveis explicativas. No caso:
Variável dependente:
- Var. 77 - UBER: 1 se a cidade possui serviço da UBER, 0 se não.
Variáveis Independentes:
- Var. 2 - CAPITAL: 1 se sim, 0 se não
- Var. 9 - POP: População residente na cidade
- Var. 19 - IDHM: Índice de Desenvolvimento Humano
- Var. 38 - TAXES: impostos pagos pela cidade
- Var. 41 - GDP_CAPITA: Pib per capita da cidade
- Var. 66 a 76 e Var. 78 a 80: Variáveis referentes a
estabelecimentos/comodidades urbanas e bens duráveis presentes na
cidade, como número de carros, hotéis, Agências de bancos, Correios,
Walmarts, McDonalds, etc.
Definindo essas variáveis no python:
# Selecionando as colunas do arquivo de acordo com as variáveis escolhidas
x_data = datam[:,[2, 4, 5, 9, 19, 38, 41, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80]]
#x_data = datam[:,[5, 10, 11, 12, 13, 14, 15]]
x_data=x_data.astype('int')
y_data = datam[:,[77]]
y_data=y_data.astype('int')
# Concatenando x e y em uma matriz
xy_data = np.hstack((x_data, y_data))
Para aplicar ML, também devemos dividir as bases em treino e teste, e dentro da de treino, em treino em si e validation. Usando os defaults 0.7/0.3 e 0.75/0.25, respectivamente:
# Dividindo os dados em 3 partes: training set, validation set e test set
num_train = int(0.75 *0.7 * x_data.shape[0]) # num de elementos no training set
num_val = int(0.25 * 0.7* x_data.shape[0]) # num de elementos no validations set
# Training set
x_train = x_data[:num_train + 1, :]
y_train = y_data[:num_train + 1]
# Validation set
x_val = x_data[num_train + 1:num_train + 1 + num_val + 1, :]
y_val = y_data[num_train + 1:num_train + 1 + num_val + 1]
# Test set
x_test = x_data[num_train + 1 + num_val + 1:, :]
y_test = y_data[num_train + 1 + num_val + 1:]
Por fim, aplicando os testes:
# Classificação linear (benchmark)
lin_model = linear_model.SGDClassifier(loss = "log",
penalty = "none", max_iter = 10^100,
tol = 1e-5,
random_state = RANDOM_SEED)
lin_model.fit(x_train, y_train)
accuracy = lin_model.score(x_val, y_val)
print("A acurácia do modelo linear no validation set é: " + str(accuracy))
A acurácia do modelo linear no validation set é: 0.8002049180327869
# SVM linear
svm_lin_model = linear_model.SGDClassifier(loss = "hinge",
penalty = "l2", alpha = 1e-1,
max_iter = 10^100,
tol = 1e-5,
random_state = RANDOM_SEED)
svm_lin_model.fit(x_train, y_train)
accuracy = svm_lin_model.score(x_val, y_val)
print("A acurácia do SVM linear no validation set é: " +
str(accuracy))
A acurácia do SVM linear no validation set é: 0.7950819672131147
# SVM não linear
svm_nonlinear_model = svm.NuSVC(nu=0.01, kernel = "poly", degree = 2,
max_iter = 10^10,
tol = 1e-5, random_state = RANDOM_SEED)
svm_nonlinear_model.fit(x_train, y_train)
accuracy = svm_nonlinear_model.score(x_val, y_val)
print("A acurácia do SVM não linear no validation set é: "
+str(accuracy))
A acurácia do SVM não linear no validation set é: 0.944672131147541
Logo, notamos pela análise no validation set que a maior acurácia é obtida com o modelo SVM não linear. Todavia, como essa acurácia é muito próxima de 1, há indícios fortes de overfitting, sendo assim mais indicado usar o segundo melhor modelo, que é o de classificação linear.
Analisando por fim no test set:
accuracy_lin_test = lin_model.score(x_test, y_test)
accuracy_svm_lin_test = svm_lin_model.score(x_test, y_test)
accuracy_svm_nonlinear_test = svm_nonlinear_model.score(x_test, y_test)
print(accuracy_lin_test)
0.7811004784688995
print(accuracy_svm_lin_test)
0.7799043062200957
print(accuracy_svm_nonlinear_test)
0.9300239234449761
Notamos padrão similar ao do validation set no test set. Logo, o modelo preferido para prever a presença de Uber nas cidades brasileiras é o de classificação linear, visto que possui a mais alta acurácia dentre os que não possuem indícios de overfitting.