Brincando com dados: Vencedores do Oscar Parte 2


Oscar Winner

Olá a todos, esse post é a segunda parte de um conjunto de posts intítulados “Brincando com os dados”. A primeira parte foi sobre como trabalhar com pymongo e fazer o carregamento dos filmes indicados a melhor filme do Oscar.

Esse segundo post será sobre análise de dados, vamos pegar os dados salvos na primeira parte e verificar se existem atributos que indicam que um filme será o vencedor ou não. Ao final dessa postagem iremos tentar prever qual será o ganhador do Oscar de 2016.

Novamente, vamos trabalhar com PyMongo para buscar os dados no MongoDB. Para visualizar os dados vamos utilizar uma biblioteca de Machine Learning chamada GraphLab create da empresa Dato.

De forma que o post fique mais simples em termos de código, estou usando aqui o html gerado pelo próprio IPython Notebook, então os comentários e o código estão entrelaçados.

Preparativos

Para ficar mais simples e didático decidimos utilizar o IPython 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 IPython Notebook baixe o arquivo: ImportingOscarRunners.ipynb

Base

MongoDB: O MongoDB é um 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.

GraphLab Create: É uma biblioteca de machine learning.

PyMongo: PyMongo é uma biblioteca em python para acessar o MongoDB.


import graphlab
import json
from pymongo import MongoClient


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

i = 0
movies = []
for document in movie_cursor: 
    movies.append(document)    

Carregamento dos dados

Inicialmente, criamos um cliente de mongodb e utilizamos a variável “db” para referenciar a database “imdb” e para fazer operações nos filmes da coleção “movies” utilizamos a variável movie_db.

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


sf = graphlab.SFrame(movies)    
movies_sframe = sf.unpack('X1', column_name_prefix="")

A biblioteca GraphLab normalmente utiliza objetos SFrame para representar seus dados, nesse caso utilizamos a construtora que recebe uma lista e utilizamos a função unpack para transformar cada entrada da lista, que é um dicionário no formato do SFrame.

# looking at the data, only the 4 first results
movies_sframe.head(4)
_id assistant director budget cast casting director
1790885 [{‘name’: 'Tarik Afifi’,
'id’: '3199917’}, …
40000000 [{'name’: 'Jason Clarke’,
'id’: '0164809’}, …
[{'name’: 'Mark Bennett’,
'id’: '0071916’}, …
1655442 [{'name’: 'James Canal’,
'id’: '0133511’}, …
15000000 [{'name’: 'Jean
Dujardin’, 'id’: …
[{'name’: 'Heidi Levitt’,
'id’: '0506217’}] …
2505072 [{'name’: 'John
Bonaccorse’, 'id’: …
0 [{'name’: 'Martin
Henderson’, 'id’: …
[{'name’: 'Libby
Goldstein’, 'id’: …
1454029 [{'name’: 'Karen Davis’,
'id’: '0204929’}, …
25000000 [{'name’: 'Emma Stone’,
'id’: '1297015’}, …
[{'name’: 'Kerry Barden’,
'id’: '0054234’}, …
countries director distributors editor
[USA] [{'name’: 'Kathryn
Bigelow’, 'id’: …
[{'name’: 'A-Film
Distribution’, 'id’: …
[{'name’: 'William
Goldenberg’, 'id’: …
[France] [{'name’: 'Michel
Hazanavicius’, 'id’: …
[{'name’:
'Cin\xc3\xa9art’, 'id’: …
[{'name’: 'Anne-Sophie
Bion’, 'id’: '2691134’}, …
[USA] [{'name’: 'Randall
Einhorn’, 'id’: …
[{'name’: 'SundanceTV’,
'id’: '0490233’}, …
[{'name’: 'Kristina
Boden’, 'id’: '009086 …
[USA, India, United Arab
Emirates] …
[{'name’: 'Tate Taylor’,
'id’: '0853238’}] …
[{'name’: 'Touchstone
Pictures’, 'id’: …
[{'name’: 'Hughes
Winborne’, 'id’: …
genres languages opening_weekend original music oscar_year
[Drama, History,
Thriller] …
[English, Arabic] 417150 [{'name’: 'Alexandre
Desplat’, 'id’: …
2013
[Comedy, Drama, Romance] [English, English,
French] …
204878 [{'name’: 'Ludovic
Bource’, 'id’: …
2012
[Drama] [English] 0 [{'name’: 'Daniel Licht’,
'id’: '0006171’}] …
2012
[Drama] [English] 26044590 [{'name’: 'Thomas
Newman’, 'id’: …
2012
plot production companies runtime special effects companies title
[Maya is a CIA operative
whose first experienc …
[{'name’: 'Columbia
Pictures’, 'id’: …
[157] [{'name’: 'Image Engine
Design’, 'id’: …
Zero Dark Thirty
[Outside a movie
premiere, enthusiastic …
[{'name’: 'Studio 37’,
'id’: '0210188’}, …
[100] [{'name’: 'Digital
District’, 'id’: …
The Artist
[Revolves around a local
cop struggling to keep …
[] [60] [] The Descendants
[Set in Mississippi
during the 1960s, Ske …
[{'name’: 'DreamWorks
SKG’, 'id’: '0040938’}, …
[USA:146] [{'name’: 'Pixel Magic’,
'id’: '0065379’}] …
The Help
user_rating winner writer
7.4 None [{'name’: 'Mark Boal’,
'id’: '1676793’}] …
8.0 1 [{'name’: 'Michel
Hazanavicius’, 'id’: …
7.4 None [{'name’: 'Aaron
Guzikowski’, 'id’: …
8.1 None [{'name’: 'Tate Taylor’,
'id’: '0853238’}, …
[4 rows x 22 columns]

A função head() do SFrame mostra as primeiras linhas e o cabeçalho dessa “matriz”. É importante dar uma olhada para saber qual tipo de dados estamos lidando, se o formato e tipo estão corretos.

Visualizando Dados

# now we set the target to this window (ipython notebook)
graphlab.canvas.set_target('ipynb')
# we use the show function, this function show some metrics about each feature
movies_sframe.show(view="Summary")

Oscar Winner

O Graphlab tem um sistema de visualizações bem interessante e simples, para visualizar direamente no python notebook utilizamos a função graphlab.canvas.set_target(“ipynb”). Depois, para ver uma resumo dos dados de um SFrame podemos utilizar a função show()*.

*No caso, quando exporto o arquivo ele não gera a visualização, então estou adicionando aqui uma imagem para mostrar como os dados são mostrados.

A função show() gera uma tabela com todas as colunas da matriz, gerando informações bem simples mas interesantes, como:

  • Tipo
  • Número de valores únicos
  • Número de entradas com esse coluna vazia ou undefined
  • Valor máximo dessa coluna
  • Valor mínimo dessa coluna
  • Mediana
  • Média
  • Desvio padrão
  • Itens mais frequentes

Para colunas numéricas ele mostra um gráfico de distribuição.

# now we take only the Oscar winners
oscar_winners = movies_sframe[movies_sframe['winner'] == 1]
oscar_winners.show(view="Summary")

Oscar Winner

Agora vamos utilizar outra funcionalidade muito legal do SFrame. É possível utilizar um filtro, retornando outro SFrame em que os valores respeitam a expressão boleana.

Nesse caso, utilizamos a expressão boleana “movies_sframe['winner’] == 1” para filtrar apenas os vencedores do Oscar, logo depois, utilizamos denovo a função show(), agora nesse novo SFrame.

Analisando um pouco esse sumário dos filmes vencedores do oscar podemos perceber que filmes de Drama dominam, além disso, é interessante analisar um pouco as notas no imdb: A média e a mediana ficaram em 8, o filme de menor nota teve 7.2. Qual será que foi esse filme? Vamos verificar.


print "Título: " + oscar_winners[oscar_winners['user_rating'] == 7.2]['title'][0]
print "Ano: " + str(oscar_winners[oscar_winners['user_rating'] == 7.2]['oscar_year'][0])

Título: Chicago
Ano: 2003

Utilizamos denovo o filtro, agora buscando qual o primeiro filme com valor de “user_rating” igual a 7.2, No caso, foi o filme Chicago do Oscar de 2003. Vamos agora ver o filme de maior avaliação dos vencedores.


print "Título: " + oscar_winners[oscar_winners['user_rating'] == 8.9]['title'][0]
print "Ano: " + str(oscar_winners[oscar_winners['user_rating'] == 8.9]['oscar_year'][0])

Título: The Lord of the Rings: The Return of the King
Ano: 2004

Frodo

Como nosso querido Frodo pode mostrar com seu sorriso, o filme de maior nota que levou a estatueta foi “Senhor dos Anéis. Retorno do Rei”.

Vamos agora analisar algumas features dos vencedores do oscar e comparar com todos os filmes que concorreram mas NÃO ganharam. Para isso vamos usar a função show() relativo ao tipo SArray. No caso o show padrão mostra dados como mínimo, máximo, média e um gráfico com os valores. Vamos visualizar então agora os ratings dos concorrentes e depois dos vencedores.


graphlab.canvas.set_target('ipynb')
oscar_losers = movies_sframe[movies_sframe['winner'] == None]
oscar_losers['user_rating'].show()
oscar_winners['user_rating'].show()

Barras

Existe uma pequena diferença entre todos os filmes que não ganharam com os que levaram a estatueta, aparentemente os vencedores do oscar possuem uma nota mais alta do que os que não ganharam. ( média e mediana maiores no segundo caso)
Agora vamos comparar o tempo de duração dos filmes que concorreram com os que ganharam. Mas antes disso, precisamos trabalhar nos dados, alguns tempos estão em formato string do tipo “Extended cut: 130”.


import re
p = re.compile('([0-9]+)')
runtime_list = []
#first we will transform every runtime into a number
for movie in movies_sframe: 
    match = p.search(movie['runtime'][0])    
    if len(match.groups()) > 0:
        runtime_list.append(int(match.group(0)))
    else:
        runtime_list.append(0)

movies_sframe.add_column(graphlab.SArray(runtime_list),name='runtime_oficial') 

print movies_sframe['runtime_oficial'].show()

Barras

Nos criamos um lista com o resultado de um regex simples que busca apenas os números da duração (em minutos). Logo depois, adicionamos ao nosso SFrame uma coluna nomeada runtime_oficial e mostramos o resultado dele, percebe-se que todos os valores fazem sentido.

# first lets fill the winner field with 0 when None
movies_sframe['winner'] = movies_sframe['winner'].fillna(0)
movies_sframe['budget'] = movies_sframe['budget'].fillna(0)
movies_sframe['opening_weekend'] = movies_sframe['opening_weekend'].fillna(0)

#print movies_sframe[movies_sframe['budget'] == 0]["title"]
#print movies_sframe[movies_sframe['opening_weekend'] == 0]["title"]
movies_sframe['budget'] = movies_sframe.apply(lambda x: 35000000 if x['title'] == 'The Descendants' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 7500000 if x['title'] == 'An Education (2009)' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 40000000 if x['title'] == 'Extremely Loud & Incredibly Close' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 15000000 if x['title'] == 'The Queen (2006)' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 30000000 if x['title'] == 'The Grand Budapest Hotel' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 6000000 if x['title'] == 'Room' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 10000000 if x['title'] == 'Brooklyn' else x['budget'])
movies_sframe['budget'] = movies_sframe.apply(lambda x: 20000000 if x['title'] == 'Spotlight' else x['budget'])

movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 15371203   if x['title'] == 'Bridge of Spies' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 11201500  if x['title'] == 'Room' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 1190096 if x['title'] == 'The Descendants' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 159017 if x['title'] == 'An Education (2009)' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 68266 if x['title'] == 'Amour' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 72348 if x['title'] == 'Extremely Loud & Incredibly Close' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 208763 if x['title'] == 'The Theory of Everything' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 135388 if x['title'] == 'Whiplash' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 260382 if x['title'] == 'Her (2013)' else x['opening_weekend'])
movies_sframe['opening_weekend'] = movies_sframe.apply(lambda x: 128435 if x['title'] == 'Philomena' else x['opening_weekend'])

# now we create another column with only on genre
movies_sframe['main_genre'] = movies_sframe.apply(lambda x: str(x['genres'][0]))

Nessa parte do código estamos preenchendo com 0 os campos inexistentes usando a função fillna(0) e preenchendo os campos de budget e openining_weekend de alguns filmes que não possuiam.

Na próxima etapa, vamos adicionar novos campos ao nosso SFrame, para cada um dos prêmios escolhidos vamos adicionar um campos que valerá 1 se o filme ganhou aquela premiação e 0 se não.


# Now we are going to add the Sag Winners
sag_winners = ["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 = ["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 = ["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 = ["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"]

wga_winners = ["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 = ['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"]

movies_sframe['sag_winner'] = movies_sframe.apply(lambda x: 1 if x['title'] in sag_winners else 0)
movies_sframe['golden_globe'] = movies_sframe.apply(lambda x: 1 if x['title'] in golden_globe else 0) 
movies_sframe['nyfcc_winner'] = movies_sframe.apply(lambda x: 1 if x['title'] in nyfcc_winners else 0)
movies_sframe['dga_winner'] = movies_sframe.apply(lambda x: 1 if x['title'] in dga_winners else 0)
movies_sframe['wga_winner'] = movies_sframe.apply(lambda x: 1 if x['title'] in wga_winners else 0)
movies_sframe['pga_winner'] = movies_sframe.apply(lambda x: 1 if x['title'] in pga_winners else 0)

Utilizamos as premiações mais reconhecidas por serem “termômetros” do oscar e o Golden Globes.

Utilizamos nessa parte a função “apply()” do SFrame, ela aplica uma operação a cada elemento do SFrame, retornando um SFrame. Nesse caso, nós verificamos se o título do filme atual está na lista de vencedores de cada prêmio e adicionamos 1 se sim e 0 se não.

Na pŕoxima etapa vamos analisar quantas vezes os vencedores coincidiram, isto é, quantas vezes cada premiação coincidiu com o Oscar.


# now we check which prizes coincide more 
sag_oscar = movies_sframe.apply(lambda x: x['title'] if ((x['sag_winner'] * x['winner']) == 1) else 'none', dtype=str)
sag_oscar = sag_oscar.filter(lambda x: x != 'none')
print "Sag: " + str(len(sag_oscar))

golden_oscar = movies_sframe.apply(lambda x: x['title'] if x['golden_globe'] * x['winner'] == 1 else None, dtype=str)
golden_oscar = golden_oscar.filter(lambda x: x != None)
print "Golden Globes: " + str(len(golden_oscar))

ny_oscar = movies_sframe.apply(lambda x: x['title'] if x['nyfcc_winner'] * x['winner'] == 1 else None, dtype=str)
ny_oscar = ny_oscar.filter(lambda x: x != None)
print "NYFCC: " + str(len(ny_oscar))

dga_oscar = movies_sframe.apply(lambda x: x['title'] if x['dga_winner'] * x['winner'] == 1 else None, dtype=str)
dga_oscar = dga_oscar.filter(lambda x: x != None)
print "DGA: " + str(len(dga_oscar))

wga_oscar = movies_sframe.apply(lambda x: x['title'] if x['wga_winner'] * x['winner'] == 1 else None, dtype=str)
wga_oscar = wga_oscar.filter(lambda x: x != None)
print "WGA: " + str(len(wga_oscar))

pga_oscar = movies_sframe.apply(lambda x: x['title'] if x['pga_winner'] * x['winner'] == 1 else None, dtype=str)
pga_oscar = pga_oscar.filter(lambda x: x != None)
print "PGA: " + str(len(pga_oscar))

bafta_oscar = movies_sframe.apply(lambda x: x['title'] if x['bafta_winner'] * x['winner'] == 1 else None, dtype=str)
bafta_oscar = bafta_oscar.filter(lambda x: x != None)
print "BAFTA: " + str(len(bafta_oscar))

Sag: 8
Golden Globes: 7
NYFCC: 4
DGA: 12
WGA: 7
PGA: 11
BAFTA: 8

Podemos perceber que os dois melhores termômetros do Oscar são:

  • DGA (Directors Guild of America Award): 12 ocasiões
  • PGA (Producers Guild of America Award): 11 ocasiões

Os piores são:

  • NYFCC: 4 ocasiões
  • Golden Globes: 7 ocasiões (contando aqui melhor filme de drama E comédia e musical)

Agora vamos fazer um pequeno experimento, vamos usar os vencedores dessas premiações e alguns valores dos filmes para tentar prever a probabilidade de cada indicado ser o vencedor do Oscar.

Para os atributos, utilizei as premiações que deram o melhor resultado e alguns campos que já existem em nossa tabela.

Utilizamos o algoritmo de random_forest_classifier.

Para verificar o resultado anotamos quantas vezes acertamos o ganhador na primeira tentativa ou se ele estava presente em nosso top 3.


features = ["bafta_winner","pga_winner","dga_winner", "golden_globe", "sag_winner", "budget", "opening_weekend", "runtime_oficial", "user_rating"]

print 'Features:' + str(features)

years = range(2001,2016)
print years

top3_correct = 0
top1_correct = 0
for year in years:        
    train_data = movies_sframe[movies_sframe['oscar_year'] != year and movies_sframe['oscar_year'] != 2016]
    model = graphlab.random_forest_classifier.create(train_data, target='winner', features=features, verbose=False, num_trees=50)
    test_data = movies_sframe[movies_sframe['oscar_year'] == year]

    results = model.predict_topk(test_data, k=2)
    result_sorted = results[results['class'] == 1].sort("probability")
    #print result_sorted
    first = len(results[results['class'] == 1])-1
    second = len(results[results['class'] == 1])-2
    third = len(results[results['class'] == 1])-3

    top3 = []
    top3.append(test_data['title'][result_sorted[first]['id']])
    top3.append(test_data['title'][result_sorted[second]['id']])
    top3.append(test_data['title'][result_sorted[third]['id']])
    top1 = test_data['title'][result_sorted[first]['id']]


    if test_data[test_data['winner'] == 1][0]['title'] in top3:
        top3_correct = top3_correct + 1
    if test_data[test_data['winner'] == 1][0]['title'] == top1:
        top1_correct = top1_correct + 1        

    print '\n\nVencedor real:' + test_data[test_data['winner'] == 1][0]['title']
    print '----------'
    print 'Vencedor previsto: ' + test_data['title'][result_sorted[first]['id']]
    print 'Segundo previsto: ' + test_data['title'][result_sorted[second]['id']]
    print 'Terceito previsto: ' + test_data['title'][result_sorted[third]['id']]

print 'Acertos em 3: ' + str(top3_correct)
print 'Acertos em 1: ' + str(top1_correct)

print 'Acurácia em 3: ' + str(top3_correct/float(15))
print 'Acurácia: ' + str(top1_correct/float(15))
Features:['pga_winner', 'dga_winner', 'golden_globe', 'sag_winner', 'budget', 'opening_weekend', 'runtime_oficial', 'user_rating']
[2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015]


Vencedor real:Gladiator
----------
Vencedor previsto: Gladiator
Segundo previsto: Crouching Tiger, Hidden Dragon
Terceito previsto: Traffic


Vencedor real:A Beautiful Mind
----------
Vencedor previsto: A Beautiful Mind
Segundo previsto: Moulin Rouge!
Terceito previsto: The Lord of the Rings: The Fellowship of the Ring


Vencedor real:Chicago
----------
Vencedor previsto: Chicago
Segundo previsto: The Pianist
Terceito previsto: The Lord of the Rings: The Two Towers


Vencedor real:The Lord of the Rings: The Return of the King
----------
Vencedor previsto: The Lord of the Rings: The Return of the King
Segundo previsto: Mystic River
Terceito previsto: Seabiscuit


Vencedor real:Million Dollar Baby
----------
Vencedor previsto: Million Dollar Baby
Segundo previsto: The Aviator
Terceito previsto: Sideways


Vencedor real:Crash
----------
Vencedor previsto: Brokeback Mountain
Segundo previsto: Crash
Terceito previsto: Munich


Vencedor real:The Departed
----------
Vencedor previsto: The Departed
Segundo previsto: Little Miss Sunshine (2006)
Terceito previsto: The Queen (2006)


Vencedor real:No Country for Old Men
----------
Vencedor previsto: No Country for Old Men
Segundo previsto: There Will Be Blood
Terceito previsto: Michael Clayton


Vencedor real:Slumdog Millionaire
----------
Vencedor previsto: Slumdog Millionaire
Segundo previsto: The Reader
Terceito previsto: Milk


Vencedor real:The Hurt Locker
----------
Vencedor previsto: The Hurt Locker
Segundo previsto: Inglorious Bastards
Terceito previsto: up


Vencedor real:The King's Speech
----------
Vencedor previsto: The King's Speech
Segundo previsto: Inception
Terceito previsto: Winter's Bone


Vencedor real:The Artist
----------
Vencedor previsto: The Artist
Segundo previsto: The Help
Terceito previsto: War Horse


Vencedor real:Argo
----------
Vencedor previsto: Argo
Segundo previsto: Django Unchained
Terceito previsto: Beasts of the Southern Wild


Vencedor real:12 Years a Slave
----------
Vencedor previsto: 12 Years a Slave
Segundo previsto: Gravity
Terceito previsto: The Wolf of Wall Street


Vencedor real:Birdman
----------
Vencedor previsto: Birdman
Segundo previsto: Whiplash
Terceito previsto: Imitation Game
Acertos em 3: 15
Acertos em 1: 14
Acurácia em 3: 1.0
Acurácia: 0.9333333

Considerando o top 3 acertamos 15 vezes das 15. Mas no caso de considerar apenas o filme de maior probabilidade foram 14 acertos de 15 possíveis. Sendo que, sinceramente, “Brokeback Mountain” deveria ter ganhado de “Crash”, logo, considero que nós acertamos e o Oscar errou =P

Essa forma de avaliar um algoritmo é chamada de Leave-one-out que é praticamente um k-fold cross validation que o k=n, sendo n o número de itens a serem testados.

Agora vamos tentar adivinhar o ganhador do Oscar de 2016 =D

PS: Estou rodando com os atributos do dia 12 de fevereiro.

train_data = movies_sframe[movies_sframe['oscar_year'] != 2016]
model = graphlab.random_forest_classifier.create(train_data, target='winner', features=features, verbose=False, num_trees=50)
test_data = movies_sframe[movies_sframe['oscar_year'] == 2016]

results = model.predict_topk(test_data, k=2)
result_sorted = results[results['class'] == 1].sort("probability")
#print result_sorted
first = len(results[results['class'] == 1])-1
second = len(results[results['class'] == 1])-2
third = len(results[results['class'] == 1])-3

top3 = []
top3.append(test_data['title'][result_sorted[first]['id']])
top3.append(test_data['title'][result_sorted[second]['id']])
top3.append(test_data['title'][result_sorted[third]['id']])
top1 = test_data['title'][result_sorted[first]['id']]

print '----------'
print 'Vencedor previsto: ' + test_data['title'][result_sorted[first]['id']]
print 'Segundo previsto: ' + test_data['title'][result_sorted[second]['id']]
print 'Terceito previsto: ' + test_data['title'][result_sorted[third]['id']]
----------
Vencedor previsto: The Revenant
Segundo previsto: The Big Short
Terceito previsto: Spotlight

Oscar

Pelo nosso top 3 o filme com maior probabilidade de ganhar é “O Regresso” do nosso querido Leonardo DiCaprio, logo depois dele está o “A Grande Aposta” que ganhou o PGA.

Logicamente, isso foi só um pequeno exemplo, para mostrar algumas funcionalidades dessas ferramentas, para criar um classificador é necessário muitos exemplos, apenas 15 exemplos positivos é um número muito pequeno.

No próximo post, pretendo buscar os dados no MySQL e fazer um classificador mais interessante com mais exemplos, mostrando algumas técnicas de Machine Learning.

Abraços e até a próxima

Tags: python, imdb, data science, dados, mongodb, pymongo, IMDbPy, oscar, movie, filme, and Ipython Notebook

Related Posts

Brincando com dados: Prevendo ganhadores do Oscar de 2017

No último post 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”.

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 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.