Brincando com dados: Prevendo ganhadores do Oscar de 2017


Olá a todos!

No último post analisamos as features do Rotten Tomatoes. Agora, vamos juntar todas as features relativas as principais premiações com as geradas utilizando os valores do Rotten Tomatoes e tentar prever quais serão os ganhadores dos Oscar de “Melhor Filme”, “Melhor Atriz” e “Melhor Ator”.

et

Antes de cada previsão vou falar quais são os meus indicados preferidos, porque além de mente eu também tenho um coração. =P

Objetivo

O objetivo desse post é mostrar a criação de algumas features novas baseadas em outras já existentes, além demonstrar funções e possibilidades da biblioteca scikit-learn de python para aprendizado de máquina.

Preparativos

A fim de tornar o processo mais simples e didático, decidimos utilizar o Jupyter Notebook. Para fazer a instalação dele, siga o tutorial descrito aqui: http://jupyter.readthedocs.org/en/latest/install.html

Para rodar o código ou acompanhar o post pelo Jupyter Notebook baixe o arquivo https://github.com/lfomendes/oscarPredictions/blob/master/Oscar%20Analysis%202017.ipynb

Base

Scikit-learn: biblioteca de python mais utilizada para o fluxo de aprendizado de máquina, com funções de pré-processamento, algoritmos e funções de avaliação.

MongoDB : banco de dados não relacional. Ele é orientado a documentos e utiliza um formato chamado BSON, bem próximo ao JSON. Ele é bem simples de entender e utilizar.

Pandas: biblioteca de python para estrutura e análise de dados.

PyMongo: biblioteca em python para acessar o MongoDB.

Votação do Oscar

Antes de avançarmos, precisamos definir como funciona a votação do Oscar. Ela é um pouco peculiar, o que torna a tarefa de descobrir o vencedor mais complicada.

Vou colocar aqui um link para um texto e um vídeo que ajudam a entender essa “fórmula” maluca:

[Texto] http://g1.globo.com/pop-arte/oscar/2016/noticia/2016/02/oscar-2016-entenda-como-funciona-o-processo-de-votacao-da-academia.html

[Vídeo] Como ganhar o bolão do Oscar? - Fora do Padron #5


et

Meus preferidos

Antes de entrarmos no código em si, quero aproveitar essa oportunidade para criar uma conexão pessoal com você, leitor. Por isso, vou colocar aqui minha opinião sobre os indicados a melhor filme.

Indicados

  • “La La Land”
  • “Lion”
  • “Moonlight”
  • “Manchester by the Sea”
  • “Hidden Figures”
  • “Arrival”
  • “Hacksaw Ridge”
  • “Fences”
  • “Hell or High Water”

Dos indicados o único que não vi foi “Fences”.

Meu preferido do ano de 2016

Capitão Fantástico - Sei que não está indicado a melhor filme, mas foi meu preferido de 2016. Uma linda e inesperada pérola do fatídico ano de 2016.

Meu preferido dos indicados

Essa é uma decisão difícil. Nesse ano temos filmes com histórias fortes, que tocam sentimentos profundos e passam mensagens importantes (e temos também “La la land”).

et

Brincadeiras à parte, eu gostei MUITO de Arrival (A Chegada) e de Moonlight . “Lion”, “Manchester by the Sea” e “Hidden Figures” são ótimos filmes também, mas acho que se eu pudesse escolher…

et


Meu MENOS preferido dos indicados

Gente, eu gostei de “La la land”. É, com certeza, um bom filme, mas acho ele superestimado. Já “Hacksaw Ridge” - “Até o Último Homem” é um filme com uma história real muito interessante, mas para mim a direção do Mel Gibson exagerou em várias cenas, além de eu não concordar muito com a visão dele de mundo.

Para finalizar vou deixar uma cena maravilhosa de Moonlight.

et

Estamos utilizando a mesma base de todos os outros posts, então vamos criar a conexão com o banco e pegar uma referência da coleção “movies”.

import json
from pymongo import MongoClient

client = MongoClient() # Primeiramente pegamos o client do Mongodb
db = client.imdb 
movie_db = db.movies

Atualizando vencedores dos prêmios

Vamos agora atualizar no MongoDB quais foram os vencedores das principais premiações.

# Now we are going to add the Sag Winners

sag_winners = ["Hidden Figures","Spotlight","Birdman", "American Hustle", "Argo", "The Help", "The King's Speech", 
               "Inglorious Bastards", "Slumdog Millionaire", "No Country for Old Men", "Little Miss Sunshine (2006)",
               "Crash", "Sideways", "Chicago", "The Lord of the Rings: The Return of the King", "Gosford Park", "Traffic"]

golden_globe = ['Moonlight', 'La la land' ,"The Martian","The Revenant","Boyhood", "The Grand Budapest Hotel", "12 Years a Slave", "American Hustle", "Argo", "Les Misérables", 
               "The Descendants", "The Artist", "The Social Network", "The Kids Are All Right", "Avatar", "The Hangover", 
               "Slumdog Millionaire", "Vicky Cristina Barcelona", "Atonement", "Sweeney Todd", "Babel", "Dreamgirls", 
               "Brokeback Mountain", "Walk the Line", "The Aviator", "Sideways", "The Lord of the Rings: The Return of the King",
               "Lost in Translation", "The Hours", "Chicago", "A Beaultiful Mind", "Moulin Rouge!", "Gladiator", "Almost Famous"]

nyfcc_winners = ['La la land', "Carol","Son of Saul","Boyhood", "Zero Dark Thirty", "The Artist", "The Social Network",
                 "The Hurt Locker", "Slumdog Millionaire","There Will Be Blood", "United 93", 
                 "Sideways", "Brokeback Mountain", "The Lord of the Rings: The Return of the King",
                "Far from Heaven", "Mulholland Drive"]

dga_winners = ["La la land","The Revenant","Birdman","Gravity", "Argo", "The Artist", "The King's Speech", "The Hurt Locker",
               "Slumdog Millionaire", 
               "No Country for Old Men","The Departed", "Brokeback Mountain", "Million Dollar Baby", 
               "The Lord of the Rings: The Return of the King",  "Chicago",
               "A Beautiful Mind", "Crouching Tiger, Hidden Dragon"]

#NAO SAIU AINDA - DIA 19
wga_winners = ['The Big Short',"Spotlight","The Imitation Game","The Grand Budapest Hotel", "Captain Phillips", "Her (2013)", "Argo", "Zero Dark Thirty",
               "The Descendants", 
               "Inception","The Social Network", "The Hurt Locker", "Up in the Air", "Milk", "Juno",
               "Slumdog Millionaire", "No Country for Old Men",  "The Departed",
               "Little Miss Sunshine (2006)","Brokeback Mountain", "Crash", "Sideways", "Eternal Sunshine of the Spotless Mind",
               "American Splendor", "Lost in Translations", "Bowling for Columbine", "The Hours", "A Beautiful Mind", "Gosford Park"
               , "Traffic", "You Can Count on Me"]

pga_winners = ['La la land','The Big Short', "Birdman","12 Years a Slave", "Argo", "The Artist", "The King's Speech", 
               "The Hurt Locker", "Slumdog Millionaire", "No Country for Old Men", 
               "Little Miss Sunshine", "Brokeback Mountain", "The Aviator", "The Lord of the Rings: The Return of the King",
               "Chicago", "Moulin Rouge!", "Gladiator"]

bafta_winners = ["La la land","The Revenant", "Boyhood","12 Years a Slave", "Argo", "The Artist", "The King's Speech", 
               "The Hurt Locker", "Slumdog Millionaire", "Atonement", 
               "The Queen", "Brokeback Mountain", "The Aviator", "The Lord of the Rings: The Return of the King",
               "The Pianist", "The Lord of the Rings: The Fellowship of the Ring", "Gladiator"]
# Starting everyone with false
db.movies.update_many({},{"$set": {"sag_winner": False, "golden_globe": False, 
                                   "nyfcc_winner": False,'dga_winner': False,
                                   "wga_winner": False,'pga_winner': False,
                                   "bafta_winner": False}})

for winner in sag_winners:
    db.movies.update_one({'title': winner},{"$set": {"sag_winner": True}})
for winner in golden_globe:
    db.movies.update_one({'title': winner},{"$set": {"golden_globe": True}})
for winner in nyfcc_winners:
    db.movies.update_one({'title': winner},{"$set": {"nyfcc_winner": True}})    
for winner in dga_winners:
    db.movies.update_one({'title': winner},{"$set": {"dga_winner": True}})
for winner in wga_winners:
    db.movies.update_one({'title': winner},{"$set": {"wga_winner": True}})   
for winner in pga_winners:
    db.movies.update_one({'title': winner},{"$set": {"pga_winner": True}})  
for winner in bafta_winners:
    db.movies.update_one({'title': winner},{"$set": {"bafta_winner": True}})    

Carregamento dos dados

Criamos um cursor utilizando uma consulta vazia – isto é, não estamos filtrando nada, todos os filmes serão retornados. Logo depois, iteramos pelo cursor adicionando os documentos retornados na lista “movies”.

Depois disso, vamos criar um DataFrame com todos os filmes e aplicar uma transformação em suas colunas.

movie_cursor = movie_db.find()
i = 0
movies = []
for document in movie_cursor: 
    movies.append(document)    
import pandas as pd

df = pd.DataFrame(movies)
df = df.apply(lambda x: pd.to_numeric(x, errors='ignore')) # set all columns that are a number to numeric 
df.columns.values
array(['_id', 'assistant director', 'bafta_winner', 'bafta_winners',
       'budget', 'cast', 'casting director', 'countries', 'dga_winner',
       'director', 'distributors', 'editor', 'genres', 'golden_globe',
       'languages', 'nyfcc_winner', 'opening_weekend', 'original music',
       'oscar_year', 'pga_winner', 'plot', 'production companies',
       'rotten_critic', 'rotten_people', 'rotten_position', 'runtime',
       'sag_winner', 'special effects companies', 'title', 'user_rating',
       'wga_winner', 'winner', 'writer'], dtype=object)

Vamos fazer as previsões

Primeiro vamos transformar nossa entrada em tipos que são aceitos pelo scikit. Vamos gerar um X (Matriz com features) e um Y (vetor de respostas) de entrada. O X será uma matriz com entradas numéricas/booleanas que serão nossa features, e o Y será nosso vetor de labels. , isto é, se o filme for ganhador do Oscar, ele terá valor 1, e 0 no caso contrário.

from sklearn.ensemble import ExtraTreesClassifier
from sklearn.model_selection import cross_val_score

df_with_features = df.filter(items=['budget','title','rotten_position','user_rating','pga_winner','wga_winner','sag_winner','bafta_winner','dga_winner','golden_globe','rotten_people','oscar_year','rotten_critic','nyfcc_winner','winner'])
df_with_features.head()

year_df = {}
# lets create one DF for each year
for year in df['oscar_year'].unique():
    year_df[str(year)] = df_with_features[df_with_features['oscar_year'] == year]  

Antes de qualquer coisa, vamos gerar algumas features novas. Vamos combinar entradas booleanas fazendo um AND entre elas, ou seja, a nova feature só será True se as outras duas forem True também.

Com isso teremos uma feature que demonstra se o filme ganhou os dois prêmios no mesmo ano, por exemplo.

df_with_features['pga_and_dga'] = df_with_features['pga_winner'] & df_with_features['dga_winner']
df_with_features['dga_and_sag'] = df_with_features['sag_winner'] & df_with_features['dga_winner']
df_with_features['pga_and_sag'] = df_with_features['sag_winner'] & df_with_features['pga_winner']
df_with_features['dga_and_wga'] = df_with_features['wga_winner'] & df_with_features['dga_winner']
df_with_features['pga_and_wga'] = df_with_features['wga_winner'] & df_with_features['pga_winner']

Agora vamos ver como se comportam os filmes que venceram o DGA e o PGA no mesmo ano.

df_with_features[df_with_features['pga_and_dga']].filter(items=['title','pga_and_dga','winner','oscar_year']).head(100)
title pga_and_dga winner oscar_year
5 La la land True False 2017
9 Slumdog Millionaire True True 2009
14 Chicago True True 2003
24 No Country for Old Men True True 2008
35 Brokeback Mountain True False 2006
44 The Lord of the Rings: The Return of the King True True 2004
54 Birdman True True 2015
79 The King’s Speech True True 2011
89 The Hurt Locker True True 2010
99 Argo True True 2013
108 The Artist True True 2012

Apenas o filme O Segredo de Brokeback Mountain “conseguiu” não ganhar o Oscar tendo sido o vitorioso nessas duas premiações.

Isso já mostra que o “La la land” é realmente o favorito…. Mas espera um momento. “La la land” ganhou também o WGA, o BAFTA, o Golden Globe e o NYFCC.

df_with_features['except_sag'] = df_with_features['pga_winner'] & df_with_features['dga_winner'] & df_with_features['golden_globe'] & df_with_features['nyfcc_winner'] & df_with_features['bafta_winner']

df_with_features[df_with_features['except_sag']].filter(items=['title','except_sag','winner','oscar_year']).head(100)
title except_sag winner oscar_year
5 La la land True False 2017
9 Slumdog Millionaire True True 2009
35 Brokeback Mountain True False 2006
44 The Lord of the Rings: The Return of the King True True 2004
108 The Artist True True 2012

Pouquíssimos filmes ganharam todos esses prêmios. E, novamente, “O Segredo de Brokeback Mountain” é a exceção. Talvez o Oscar tenha errado em 2006, não é mesmo?

et

Vamos agora testar um classificador com todas as features de prêmios, os votos do IMDb e as criadas a partir das notas do Rotten Tomatoes e criadas no último post.

Inicialmente vamos testar esse classificador nas premiações de 2001 a 2016 e ver quais acertamos e quais erramos.

def mk_string(collection, sep=', ', start='', end=''):
    ret = start
    for item in collection:
        ret = ret + str(item) + sep
    # Removing the last inserted separator.
    ret = ret[:len(ret) - len(sep)]
    return ret + end
from sklearn.linear_model import LogisticRegression
import numpy as np

# Vamos usar todos os outros anos para treino e ver qual a previsão para aquele ano

columns = ["pga_and_wga","dga_and_wga","pga_and_sag","dga_and_sag","pga_and_dga","user_rating", "rotten_people",'pga_winner','wga_winner','sag_winner','bafta_winner', 'dga_winner', 'golden_globe', 'rotten_critic', 'rotten_position'] 

def get_accuracy(model, df, debug= False):

    got_it = 0
    errors = []

    for year in sorted(df['oscar_year'].unique()):
        if(year == 2017):
            continue
        train = df_with_features[((df_with_features['oscar_year'] != year) & (df_with_features['oscar_year'] != 2017))] 
        test = df_with_features[df_with_features['oscar_year'] == year] 

        train_y = train["winner"].values
        train_X = train[list(columns)].values

        model = model.fit(train_X, train_y)

        test_y = test["winner"].values
        test_X = test[list(columns)].values

        probs = model.predict_proba(test_X)

        titles = np.array(test['title'].tolist())
        winner = np.array(test['winner'].tolist())

        prob_of_true = []
        i=0
        for prob in probs:
            prob_of_true.append(prob[1])

        prob_of_true = np.array(prob_of_true)   
        inds = prob_of_true.argsort()[::-1]
        if debug:
            print(inds)
            print(winner)
            print(titles)
            print(winner[inds][0])
            print(titles[inds][0])       

        if(winner[inds][0]):
            got_it += 1
        else:
            errors.append({'title':titles[inds][0],'year':year})

    accuracy = got_it/float(len(df['oscar_year'].unique())-1)    
    return got_it, errors

def print_results(acc,errors,df, model_name):
    print('Resultado para ' + model_name)
    print(str(acc) + ' acertos em ' + str(len(df['oscar_year'].unique())-1))
    accuracy = acc/float(len(df['oscar_year'].unique())-1) 
    print('Accuracy: ' + str(accuracy))
    print('\nAno do erro e qual filme foi escolhido pelo algoritmo.')
    print(mk_string(errors,sep='\n'))


logistic = LogisticRegression(solver='liblinear')
acc,errors = get_accuracy(logistic,df,False)

print_results(acc,errors,df,'Logistic Regression')
Resultado para Logistic Regression
13 acertos em 16
Accuracy: 0.8125

Ano do erro e qual filme foi escolhido pelo algoritmo.
{'year': 2005, 'title': 'The Aviator'}
{'year': 2006, 'title': 'Brokeback Mountain'}
{'year': 2016, 'title': 'The Revenant'}

Podemos ver que, com uma Regressão Logística simples, o algoritmo acertou 13 de 16 anos, apontando uma acurácia de 0.8125.

81% de acerto!!!!

crystalball

Não acertamos apenas nos anos de 2005 com “O Aviador”, 2006 com “BrokeBack Mountain” e em 2016 com “O Regresso”.

Importante salientar que, em 2005 e 2006, os filmes ganhadores eram os segundos mais prováveis da lista. Já em 2016, Spotlight estava em terceiro lugar nas probabilidades.

Agora vamos testar outros algoritmos para ver a diferença da acurácia.

from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import SGDClassifier

models = [RandomForestClassifier(n_estimators=50,n_jobs=-1,random_state=12, criterion='entropy'),
          GradientBoostingClassifier(n_estimators=200,random_state=12),
          ExtraTreesClassifier(n_jobs=-1,random_state=12),
          GaussianNB()
          ]

#"budget", "opening_weekend"
for m in models:   
    acc,errors = get_accuracy(m,df)
    print_results(acc,errors,df,str(m))
    print('\n----------------- \n')
Resultado para RandomForestClassifier(bootstrap=True, class_weight=None, criterion='entropy',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_split=1e-07, min_samples_leaf=1,
            min_samples_split=2, min_weight_fraction_leaf=0.0,
            n_estimators=50, n_jobs=-1, oob_score=False, random_state=12,
            verbose=0, warm_start=False)
13 acertos em 16
Accuracy: 0.8125

Ano do erro e qual filme foi escolhido pelo algoritmo.
{'year': 2001, 'title': 'Crouching Tiger, Hidden Dragon'}
{'year': 2006, 'title': 'Brokeback Mountain'}
{'year': 2016, 'title': 'The Revenant'}

----------------- 

Resultado para GradientBoostingClassifier(criterion='friedman_mse', init=None,
              learning_rate=0.1, loss='deviance', max_depth=3,
              max_features=None, max_leaf_nodes=None,
              min_impurity_split=1e-07, min_samples_leaf=1,
              min_samples_split=2, min_weight_fraction_leaf=0.0,
              n_estimators=200, presort='auto', random_state=12,
              subsample=1.0, verbose=0, warm_start=False)
11 acertos em 16
Accuracy: 0.6875

Ano do erro e qual filme foi escolhido pelo algoritmo.
{'year': 2001, 'title': 'Crouching Tiger, Hidden Dragon'}
{'year': 2005, 'title': 'Sideways'}
{'year': 2006, 'title': 'Brokeback Mountain'}
{'year': 2010, 'title': 'Inglorious Bastards'}
{'year': 2016, 'title': 'The Revenant'}

----------------- 

Resultado para ExtraTreesClassifier(bootstrap=False, class_weight=None, criterion='gini',
           max_depth=None, max_features='auto', max_leaf_nodes=None,
           min_impurity_split=1e-07, min_samples_leaf=1,
           min_samples_split=2, min_weight_fraction_leaf=0.0,
           n_estimators=10, n_jobs=-1, oob_score=False, random_state=12,
           verbose=0, warm_start=False)
13 acertos em 16
Accuracy: 0.8125

Ano do erro e qual filme foi escolhido pelo algoritmo.
{'year': 2005, 'title': 'The Aviator'}
{'year': 2006, 'title': 'Brokeback Mountain'}
{'year': 2016, 'title': 'The Big Short'}

----------------- 

Resultado para GaussianNB(priors=None)
13 acertos em 16
Accuracy: 0.8125

Ano do erro e qual filme foi escolhido pelo algoritmo.
{'year': 2005, 'title': 'The Aviator'}
{'year': 2006, 'title': 'Brokeback Mountain'}
{'year': 2016, 'title': 'The Big Short'}

----------------- 

Pelo visto nenhum outro algoritmo conseguiu vencer o Logistic Regression, tendo 3 deles empatados nos acertos. Interessante observar que, mesmo tendo o mesmo número de acertos, dois deles fizeram a previsão de 2016 como “A Grande Aposta” ao invés de “O Regresso”.

Agora vamos fazer uma análise da importância das features.

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import make_classification

forest = RandomForestClassifier(n_estimators=100,n_jobs=-1,random_state=12, criterion='entropy')

train = df_with_features[df_with_features['oscar_year'] != 2017] 

y = train["winner"].values
X = train[list(columns)].values

forest.fit(X, y)
importances = forest.feature_importances_
std = np.std([tree.feature_importances_ for tree in forest.estimators_],
             axis=0)
indices = np.argsort(importances)[::-1]

# Print the feature ranking
print("Feature ranking:")

for f in range(X.shape[1]):
    print("%d. feature %s (%f)" % (f + 1, columns[indices[f]], importances[indices[f]]))

# Plot the feature importances of the forest
plt.figure()
plt.title("Feature importances")
plt.bar(range(X.shape[1]), importances[indices],
       color="r", yerr=std[indices], align="center")
plt.xticks(range(X.shape[1]), indices)
plt.xlim([-1, X.shape[1]])
plt.show()
Feature ranking:
1. feature dga_winner (0.212265)
2. feature rotten_position (0.113525)
3. feature rotten_people (0.098893)
4. feature pga_winner (0.087128)
5. feature pga_and_dga (0.073356)
6. feature rotten_critic (0.069652)
7. feature user_rating (0.064661)
8. feature sag_winner (0.059707)
9. feature dga_and_sag (0.055013)
10. feature pga_and_sag (0.049090)
11. feature bafta_winner (0.034363)
12. feature dga_and_wga (0.032665)
13. feature wga_winner (0.026198)
14. feature golden_globe (0.017712)
15. feature pga_and_wga (0.005773)
et

Como já havíamos visto ano passado o DGA é o principal prêmio que “guia” o Oscar. Parece que as features rotten_position e rotten_people foram úteis para o modelo.

Podemos ver também que o golden_globe tem uma importância muito baixa no modelo criado.

et

Previsão de 2017

Apesar de neste ano “La la land” estar claramente na frente, vamos continuar o fluxo completo, montar um classificador com todos os dados até 2016 e ver qual o resultado para os Oscar desse ano.

crystalball

Vamos utilizar um Logistic Regression simples.

test = df_with_features[df_with_features['oscar_year'] == 2017] 

logistic = LogisticRegression(solver='liblinear')
logistic.fit(X, y)

X_test = test[list(columns)].values
probs = logistic.predict_proba(X_test)
titles = np.array(test['title'].tolist())

prob_of_true = []
i=0
for prob in probs:
    prob_of_true.append(prob[1])

prob_of_true = np.array(prob_of_true)   
inds = prob_of_true.argsort()[::-1]

print('Ganhador previsto: "' + titles[inds][0] + '"                Probabilidade: ' + str(prob_of_true[inds][0]))
print('Correndo pelas beiradas: "' + titles[inds][1] + '"      Probabilidade: ' + str(prob_of_true[inds][1]))
print('Correndo pelas beiradas 2: "' + titles[inds][2] + '"     Probabilidade: ' + str(prob_of_true[inds][2]))
Ganhador previsto: "La la land"                Probabilidade: 0.346224872931
Correndo pelas beiradas: "Hidden Figures"      Probabilidade: 0.0451501339342
Correndo pelas beiradas 2: "Hacksaw Ridge"     Probabilidade: 0.0210192693871
dog

Momento de dança do filme “La la land”….

É, parece que não tem para mais ninguém: vai dar “La la land” mesmo. O filme “Estrelas Além do Tempo” ficou em segundo por ter ganho o SAG e ter um alto valor na avaliação do público no Rotten Tomatoes.

dog

Agora sim, me desculpem a confusão

Agora que já fizemos a previsão de Melhor Filme, vamos tentar prever a vencedora do prêmio de melhor atriz e o vencedor de melhor ator.

Prevendo melhor atriz

Para melhor atriz temos as seguintes candidatas:

  • Emma Stone por “La La Land”
  • Isabelle Huppert por “Elle”
  • Ruth Negga por “Loving”
  • Meryl Streep por “Florence Foster Jenkins”
  • Natalie Portman por Jackie

Infelizmente, desses filmes eu só vi “La la land”, então não posso dar minha opinião pessoal. Portanto, vamos deixar os dados decidirem.

Vamos usar as seguintes features para fazer essa previsão:

  • Ganhou o Sag Award do ano
  • Ganhou o Golden Globe do ano
  • Ganhou o NYFCC do ano
  • Ganhou o BAFTA do ano
  • Ganhou o NSFCA do ano
  • Soma dos prêmios ganhos no ano
  • Quantas vezes já foi indicada para um Oscar
  • Quantas vezes já foi indicada para um Oscar e não ganhou
  • Quantas vezes já foi indicada para um Oscar e ganhou
  • Idade em décadas


dog

X_until_2016 = np.loadtxt('X_train_actress.csv', delimiter=",")
y_until_2016 = np.loadtxt('y_train_actress.csv', delimiter=",")
X_2017 = np.loadtxt('X_test_actress.csv', delimiter=",")

actress = np.array(['Emma Stone','Isabelle Huppert','Ruth Negga','Meryl Streep','Natalie Portman'])

print(X_2017)
[[  1.   1.   0.   1.   0.   3.   1.   1.   0.   2.]
 [  0.   1.   1.   0.   1.   3.   1.   1.   0.   6.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   3.]
 [  0.   0.   0.   0.   0.   0.  17.  14.   4.   6.]
 [  0.   0.   0.   0.   0.   0.   2.   1.   1.   3.]]

Estou fazendo o load das features de um arquivo externo.

rfc = RandomForestClassifier(n_estimators=1000)
rfc.fit(X_until_2016,y_until_2016)
probs = rfc.predict_proba(X_2017)

prob_of_true = []
i=0
for prob in probs:
    prob_of_true.append(prob[1])

prob_of_true = np.array(prob_of_true)   
inds = prob_of_true.argsort()[::-1]

print('Ganhadora previsto: "' + actress[inds][0] + '"               Probabilidade: ' + str(prob_of_true[inds][0]))
print('Correndo pelas beiradas: "' + actress[inds][1] + '"    Probabilidade: ' + str(prob_of_true[inds][1]))
print('Correndo pelas beiradas 2: "' + actress[inds][2] + '"      Probabilidade: ' + str(prob_of_true[inds][2]))
Ganhadora previsto: "Emma Stone"               Probabilidade: 0.989
Correndo pelas beiradas: "Isabelle Huppert"    Probabilidade: 0.367
Correndo pelas beiradas 2: "Meryl Streep"      Probabilidade: 0.04

Parece que a Emma Stone leva esse ano, sendo seguida pela “Isabelle Huppert”.

dog

Emma Stone no filme “La la land”

Lembrando a todos que a probabilidade indicada pelo algoritmo não é a chance de aquela atriz ganhar, e sim do valor do label ser True. Isto significa que o algoritmo não sabe que apenas uma pessoa ganha, e por isso a soma das probabilidades não é igual a 1.

Prevendo melhor ator

Para melhor ator temos os seguintes indicados.

  • Andrew Garfield por “Hacksaw Ridge”
  • Ryan Gosling por “La La Land”
  • Denzel Washington por “Fences”
  • Casey Affleck por “Manchester by the Sea”
  • Viggo Mortensen por “Captain Fantastic”

Desses filmes, eu ainda não vi o “Fences”, mas meu preferido para esse prêmio é o Viggo Mortensen em “Capitão Fantástico”. A atuação de Mortensen não é apenas boa; eu diria que ela é…. FANTÁSTICA!

dog

Inclusive vou mostrar aqui cenas que simbolizam como alguém consegue atuar e passar várias emoções sem falar muito. Bastam olhares e movimentos corporais.

dog

Nessa primeira cena, Viggo recebe um telefonema muito importante, enquanto na outra cena ele está sozinho em um ônibus. Inclusive já vou recomendar dois filmes em que ele atua: “Eastern Promises” e “History of Violence”.

Agora que já puxei o saco do Viggo Mortensen, vou dizer que provavelmente Casey Affleck vai ganhar (veremos nos dados) e isso não será injusto. Sua atuação em “Manchester by the Sea” é espetacular.

Nesse ano temos uma peculiaridade nessa categoria, pois Casey é um candidato fortíssimo, mas teve problemas SÉRIOS fora do set. Ele foi acusado de assédio e abuso verbal por mulheres que trabalharam no set (fonte).

dog

Isso torna essa previsão um tanto quanto difícil, pois aparentemente ele é o mais forte candidato, tendo sido o vencedor do Golden Globe, NYFCC e NSFCA ( ele perdeu apenas o SAG para Denzel Washington).

Mas como é difícil incorporar essa visão sobre a pessoa Casey Affleck, então vamos nos limitar às features de premiações para fazer essa previsão. Pessoalmente, acho difícil separar a imagem do ator de sua atuação, pois apesar de Casey estar ótimo no filme “Manchester by the sea”, as histórias que circulam a seu respeito vão e deveriam afetar os votos.

# 0 Won the Sag Award that year
# 1 Won the Golden Globes that year
# 2 Won the NYFCC that year
# 3 Won the BAFTA that year
# 4 won the NSFCA

X_until_2016 = np.loadtxt('X_train_actor.csv', delimiter=",")
y_until_2016 = np.loadtxt('y_train_actor.csv', delimiter=",")
X_2017 = np.loadtxt('X_test_actor.csv', delimiter=",")

actors = np.array(['Andrew Garfield','Denzel Washington','Casey Affleck','Viggo Mortensen','Ryan Gosling'])
print(X_2017)
[[ 0.  0.  0.  0.  0.  0.]
 [ 1.  0.  0.  0.  0.  1.]
 [ 0.  1.  1.  1.  1.  4.]
 [ 0.  0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.  1.]]

Utilizei menos features para atores, em relação às atrizes. Como eu busquei os dados de atrizes depois, acabei tendo novas ideias no caminho, então os atores ficaram apenas com as features de premiação.

rfc = RandomForestClassifier(n_estimators=1000)
rfc.fit(X_until_2016,y_until_2016)
probs = rfc.predict_proba(X_2017)

prob_of_true = []
i=0
for prob in probs:
    prob_of_true.append(prob[1])

prob_of_true = np.array(prob_of_true)   
inds = prob_of_true.argsort()[::-1]

print('Ganhador previsto: "' + actors[inds][0] + '"            Probabilidade: ' + str(prob_of_true[inds][0]))
print('Correndo pelas beiradas: "' + actors[inds][1] + '"  Probabilidade: ' + str(prob_of_true[inds][1]))
print('Correndo pelas beiradas 2: "' + actors[inds][2] + '"     Probabilidade: ' + str(prob_of_true[inds][2]))
Ganhador previsto: "Casey Affleck"            Probabilidade: 0.442384199134
Correndo pelas beiradas: "Denzel Washington"  Probabilidade: 0.164549711502
Correndo pelas beiradas 2: "Ryan Gosling"     Probabilidade: 0.124373451548

Parece que o Affleck será o grande vencedor, mas a distância para o Denzel e para Ryan Gosling não é muito grande, dado que um deles ganhou o SAG e o outro o Golden Globe.

dog

Conclusão

Para concluir, gostaria de explicar que em Aprendizado de Máquina quase nunca é possível mapear tudo que envolve uma previsão. Sempre existirá alguma variável que não dá para incorporar ao modelo (o caso do Casey Affleck, por exemplo). E é por isso que normalmente escolhemos uma métrica guia (acurácia, F1, precisão etc) e fazemos o teste com os dados antigos.

Outro ponto importante é que, no caso das previsões desse post, estou considerando que um evento de Oscar é independente dos outros. Isto significa que o Oscar de um ano não influencia no outro.

Nesse post mostramos várias fucionalidades do Scikit-learn. Espero que, com esse conhecimento, agora vocês possam brincar um pouco com essa biblioteca.

Então é isso, pessoal! Espero não demorar muito para postar novamente por aqui. =D

Abraços e bons filmes.


dog

Tags: machine learning, python, aprendizado de máquina, pandas, data analysis, análise de dados, correlation, correlação, scikit, scikit-learn, oscar, movie, filmes, La la land, and cinema

Related Posts

Brincando com dados: Análise do Oscar - Rotten Tomatoes

Finalmente chegamos àquela época do ano. Podemos chamá-la de “carnaval dos cinéfilos”, ou simplesmente de “aquela época em sabemos que a Meryl Streep será indicada”. A época das premiações mais importantes do mundo do cinema. Então vamos aproveitar essa época e fazer uma análise sobre as notas no Rotten Tomatoes dos indicados ao Oscar de melhor filme.

Prevendo evasão (churning) usando scikit-learn

Prevendo evasão de clientes em python utilizando scikit-learn.

Análise de sobrevivência (Survival Analysis)

Pequeno estudo sobre Análise de sobreviência que é um ramo da estatística que analisa tempos até ao acontecimento de determinado evento.

Brincando com dados: Descobrindo tópicos em livros com LDA

Brincando com dados: Vencedores do Oscar Parte 2

Na parte 2 vamos analisar os dados dos indicados ao prêmio de melhor filme dos últimos 15 anos e tentar prever o ganhador do ano de 2016.

Brincando com dados: Vencedores do Oscar Parte 1

O objetivo desses posts intitulados "Brincando com os dados" é dar exemplos de como importar, limpar e analisar dados. Nesse primeiro exemplo iremos importar no MongoDB os dados do IMDb dos filmes indicados a categoria de melhor filme do Oscar.

Projetando um ambiente inovador

Como criar um ambiente que estimule inovação

Gladiator Features

The manual task that became a script. The script that became a feature. The feature that defined a product.