Escolar Documentos
Profissional Documentos
Cultura Documentos
PRÁTICA E LABORATÓRIO II 1
Prática e Laboratório II
1. Orientação a Objetos
Outro princípio importante é a herança (este iremos destacar mais adiante), em que
um objeto “filho” poderá ser criado baseado em um objeto “pai”, herdando todos os
seus atributos e métodos, além de apresentar os seus próprios.
PRÁTICA E LABORATÓRIO II 2
#Criando classe
class Animal:
pass
Neste exemplo, foi utilizada a palavra reservada pass, que expressa um bloco vazio,
ou seja, sem função alguma. Note que a classe criada se inicia com letra maiúscula.
Embora esteja vazia, a classe Animal seria criada:
[‘__doc__’, ‘__module__’]
class Pessoa:
def __init__(self, nome, idade):
self.nome=nome
self.idade=idade
def obterNome(self):
return self.nome
def obterIdade(self):
return self.idade
PRÁTICA E LABORATÓRIO II 3
No exemplo, criou-se a classe Pessoa, tendo sido definidos em sua inicialização os
atributos Nome e Idade. Os métodos e/ou atributos da classe são obrigados a passar
por parâmetro ou argumento a palavra self antes de mais nada. Isso é convencionado
pelo próprio Phyton.
class Gelatina:
def __init__(self, tam, cor, sabor):
self.tam=tam
self.cor=cor
self.sabor=sabor
print gel1.tam,
print gel1.cor,
print gel1.sabor
print gel2.tam,
print gel2.cor,
print gel2.sabor
print gel3.tam,
print gel3.cor,
print gel3.sabor
PRÁTICA E LABORATÓRIO II 4
raw_input ( )
Vejamos outro exemplo prático de orientação a objetos, agora para permitir cadastro
por meio de entrada de dados:
class Produto:
def __init__(self, cod, nome, quant):
self.cod=cod
self.nome=nome
self.quant=quant
print '\n'
PRÁTICA E LABORATÓRIO II 5
print 'Dados de Saida:\n'
print 'Codigo: ' + produt.cod
print 'Produto: ' + produt.nome
print 'Quantidade: ' + produt.quant
raw_input ( )
1.2 Herança
Embora uma classe filha tenha por preceito herdar os atributos e métodos da classe
pai, a classe filha também pode apresentar seus próprios atributos e métodos.
PRÁTICA E LABORATÓRIO II 6
Na figura anterior, pode-se observar que a classe Animal é a classe pai e as classes
Cachorro, Papagaio e Mosca são classes filhas. Portanto, por exemplo, a classe filha
Cachorro apresenta como atributos espécie e cor (herdadas da classe pai) e corPelo
(próprio da classe).
# definindo Felino
PRÁTICA E LABORATÓRIO II 7
class Felino(Mamifero):
# definindo Gato
class Gato(Felino):
Qualquer forma utilizada é considerada uma sintaxe válida para o Phyton. Ainda
podemos utilizar este recurso da forma mais simplificada, por meio do símbolo “*”,
que, na verdade, indica a importação de todos os métodos, funções etc., para estarem
disponíveis no programa fonte que fez a importação.
>>> dir()
['__builtins__', '__doc__', '__name__', 'fibonacci']
>>> dir()
['__builtins__', '__doc__', '__name__', 'fib', 'fib2']
Através da instrução dir( ), foi permitido visualizar todos os detalhes acerca do módulo
utilizado (métodos, funções etc.).
O módulo sys possui várias funções, o que permite que haja uma interação com o
próprio interpretador Phyton. Podemos visualizar inicialmente as funções ps1 e ps2,
que têm por objetivo definir os prompts utilizados pelo interpretador Phyton (“>>>”
e “...”).
Neste exemplo, o prompt “>>>” foi substituído por “>” (sys.ps1) e o prompt “...” foi
substituído por “.” (sys.ps2). Só para enfatizar, o padrão seria da seguinte forma:
PRÁTICA E LABORATÓRIO II 9
>>> for i in range(10)
... print i
No exemplo a seguir, iremos utilizar a função argv, que tem por objetivo armazenar
os argumentos passados pela linha de comandos na lista de strings argv[], onde o
primeiro elemento é o nome do programa chamado, seguido pelos outros argumentos
que sejam necessários para o carregamento do programa.
# Modulo args.py
from sys import argv
print sys.argv
$ python args.py 2 5 -3
['args.py', '2', '5', '-3']
>>> sys.path
['', '/usr/lib64/python25.zip', '/usr/lib64/python2.5',
'/usr/lib64/python2.5/plat-linux2', '/usr/lib64/python2.5/libtk',
'/usr/lib64/python2.5/lib-dynload',
'/usr/lib64/python2.5/site-packages',
'/usr/lib64/python2.5/site-packages/gtk-2.0']
PRÁTICA E LABORATÓRIO II 10
Caso você queira ter acesso a informações do Phyton, como parâmetros de instalação,
por exemplo, podemos visualizar plataforma, prefixo e versão do interpretador Phyton
utilizada. Observe o código a seguir:
A função exit pode ser utilizada para encerrar uma seção do programa Phyton
diretamente. Observe a seguir:
>>> sys.exit()
$_
Quanto ao módulo re (regular expression), ele tem por objetivo fornecer ferramentas
para realizar a filtragem de strings através de expressões regulares. A primeira função
interessante desse módulo é conhecida como findall, que permite encontrar a
ocorrência de certa string, filtrando-a através de uma expressão regular. Vejamos o
exemplo abaixo:
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell
fastest')
['foot', 'fell', 'fastest']
PRÁTICA E LABORATÓRIO II 11
Outra função interessante é conhecida como sub, cujo objetivo é substituir uma
ocorrência de certa string por outra qualquer. Observe:
A função sub permite substituir duas ocorrências de uma string, assumindo apenas
uma delas. Veja:
>>> dir(math)
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan',
'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs',
'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10',
'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan',
'tanh']
Vamos recordar, através do programa exemplo a seguir, uma aplicação que utiliza uma
função matemática, neste caso, o seno de um número.
PRÁTICA E LABORATÓRIO II 12
import math
def Sin(a):
# Calcula seno de angulo em graus
ang = a*math.pi/180. # mesmo que radians()
return math.sin(ang)
Dessa forma, ao utilizar a função seno passando como parâmetro um número para
que este seno seja calculado, o mesmo será efetivado.
>>> Sin(30)
0.49999999999999994
>>> Sin(60)
0.8660254037844386
Ao executar o mesmo programa outra vez, nada impede que a mesma saída aconteça.
No entanto, outra saída diferente também será possível. Veja o exemplo:
PRÁTICA E LABORATÓRIO II 13
>>> random.randrange(10)
3
PRÁTICA E LABORATÓRIO II 14
1.7 Módulo datetime
O módulo datetime fornece classes para manipulação de datas e horas nos mais
variados formatos possíveis.
A função date (ano, mês, dia) cria um objeto do tipo data. Observe o código em
Phyton a seguir:
A resposta será 187 caracteres. Vamos comprimir a mensagem e reduzir de 187 para
143 caracteres. Observe:
PRÁTICA E LABORATÓRIO II 15
>>> z = compress(s)
>>> len(z)
Uma árvore de decisão é uma estrutura em forma de árvore usada para representar
um número de possíveis caminhos de decisão. Cada um desses caminhos leva a um
resultado específico.
PRÁTICA E LABORATÓRIO II 16
Através desse simples exemplo, é possível construir a seguinte árvore de decisão:
PRÁTICA E LABORATÓRIO II 17
Então, a classificação de um exemplo, de acordo com esta árvore, é feita da seguinte
maneira:
O atributo “aspecto” tem como valor “sol”, e o atributo “humidade” tem como valor
“elevada”. O evento em si é classificado como “não”, ou seja, quando teve sol e
humidade elevada, não teve treino de tênis. Note que neste exemplo os atributos
PRÁTICA E LABORATÓRIO II 18
“temperatura” e “vento” não foram considerados, pois não são relevantes, já que não
houve treino de tênis.
PRÁTICA E LABORATÓRIO II 19
Árvores de decisão, portanto, podem ser utilizadas para auxiliar no processo de
tomada de decisão em qualquer situação que envolva o processo decisório.
É importante saber que para construirmos uma árvore de decisão é necessário saber
quais perguntas fazer e em que ordem.
Em Phyton, basta definir uma função e colocar tudo o quer que seja parametrizado
dentro dela. Veja o exemplo abaixo:
def entropia(class_probabilidades):
””” dada a lista de probabilidades de classes, compute a entopia ”””
return sum(-p*math.log(p, 2)
for p in class_probabilidades
def entropy(class_probabilities):
"""given a list of class probabilities, compute the entropy"""
return sum(-p * math.log(p, 2) for p in class_probabilities if p)
def class_probabilities(labels):
total_count = len(labels)
return [count / total_count
for count in Counter(labels).values()]
PRÁTICA E LABORATÓRIO II 20
def data_entropy(labeled_data):
labels = [label for _, label in labeled_data]
probabilities = class_probabilities(labels)
return entropy(probabilities)
def partition_entropy(subsets):
"""find the entropy from this partition of data into subsets"""
total_count = sum(len(subset) for subset in subsets)
Para a criação da árvore de decisão, é necessário ter uma boa base de dados para
poder manipular. Segue um exemplo utilizado por Grus (2016):
if __name__ == "__main__":
inputs = [
({'level':'Senior','lang':'Java','tweets':'no','phd':'no'}, False),
({'level':'Senior','lang':'Java','tweets':'no','phd':'yes'}, False),
({'level':'Mid','lang':'Python','tweets':'no','phd':'no'}, True),
({'level':'Junior','lang':'Python','tweets':'no','phd':'no'}, True),
({'level':'Junior','lang':'R','tweets':'yes','phd':'no'}, True),
({'level':'Junior','lang':'R','tweets':'yes','phd':'yes'}, False),
({'level':'Mid','lang':'R','tweets':'yes','phd':'yes'}, True),
({'level':'Senior','lang':'Python','tweets':'no','phd':'no'}, False),
({'level':'Senior','lang':'R','tweets':'yes','phd':'no'}, True),
({'level':'Junior','lang':'Python','tweets':'yes','phd':'no'}, True),
PRÁTICA E LABORATÓRIO II 21
({'level':'Senior','lang':'Python','tweets':'yes','phd':'yes'},True),
({'level':'Mid','lang':'Python','tweets':'no','phd':'yes'}, True),
({'level':'Mid','lang':'Java','tweets':'yes','phd':'no'}, True),
({'level':'Junior','lang':'Python','tweets':'no','phd':'yes'},False)
]
A partir daí, precisamos encontrar a partição com entropia mínima para todos os
conjuntos de dados:
A menor entropia vem da divisão baseada em level, então precisamos fazer uma
subárvore para cada valor level possível.
Considerando que árvores de decisão podem se ajustar quase que perfeitamente, seus
dados em treinamento, não nos surpreende quando eles tentam se reajustar.
def entropy(class_probabilities):
"""given a list of class probabilities, compute the entropy"""
return sum(-p * math.log(p, 2) for p in class_probabilities if p)
def class_probabilities(labels):
total_count = len(labels)
return [count / total_count
for count in Counter(labels).values()]
def data_entropy(labeled_data):
labels = [label for _, label in labeled_data]
probabilities = class_probabilities(labels)
return entropy(probabilities)
def partition_entropy(subsets):
"""find the entropy from this partition of data into subsets"""
total_count = sum(len(subset) for subset in subsets)
PRÁTICA E LABORATÓRIO II 23
return groups
def partition_entropy_by(inputs,attribute):
"""computes the entropy corresponding to the given partition"""
partitions = partition_by(inputs, attribute)
return partition_entropy(partitions.values())
PRÁTICA E LABORATÓRIO II 24
# if this is our first pass,
# all keys of the first input are split candidates
if split_candidates is None:
split_candidates = inputs[0][0].keys()
PRÁTICA E LABORATÓRIO II 25
subtrees[None] = num_trues > num_falses # default case
if __name__ == "__main__":
inputs = [
({'level':'Senior','lang':'Java','tweets':'no','phd':'no'}, False),
({'level':'Senior','lang':'Java','tweets':'no','phd':'yes'}, False),
({'level':'Mid','lang':'Python','tweets':'no','phd':'no'}, True),
({'level':'Junior','lang':'Python','tweets':'no','phd':'no'}, True),
({'level':'Junior','lang':'R','tweets':'yes','phd':'no'}, True),
({'level':'Junior','lang':'R','tweets':'yes','phd':'yes'}, False),
({'level':'Mid','lang':'R','tweets':'yes','phd':'yes'}, True),
({'level':'Senior','lang':'Python','tweets':'no','phd':'no'}, False),
({'level':'Senior','lang':'R','tweets':'yes','phd':'no'}, True),
({'level':'Junior','lang':'Python','tweets':'yes','phd':'no'}, True),
({'level':'Senior','lang':'Python','tweets':'yes','phd':'yes'},True),
({'level':'Mid','lang':'Python','tweets':'no','phd':'yes'}, True),
({'level':'Mid','lang':'Java','tweets':'yes','phd':'no'}, True),
({'level':'Junior','lang':'Python','tweets':'no','phd':'yes'},False)
]
PRÁTICA E LABORATÓRIO II 26
for key in ['level','lang','tweets','phd']:
print key, partition_entropy_by(inputs, key)
print
raw_input( )
PRÁTICA E LABORATÓRIO II 27
Observe a saída do programa:
Neste caso, através da técnica floresta aleatória, podemos construir várias árvores de
decisão, deixando-as escolher como classificar as entradas possíveis.
Uma rede neural artificial é um modelo preditivo motivado pela forma como o cérebro
humano funciona. (GRUS, 2016).
PRÁTICA E LABORATÓRIO II 28
Redes neurais artificiais consistem em neurônios artificiais que desenvolvem cálculos
similares acerca de suas entradas. Esse tipo de estrutura é muito útil para os cientistas
de dados, pois podem resolver uma grande variedade de problemas, como
reconhecimento de caligrafia, detecção facial etc.
2.6 Perceptrons
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pesos (sinapses)
w = [0,0,0,0]
# entradas
x = [[-1,-1,1,1],
[1,1,1,1],
[1,1,-1,1],
[-1,-1,-1,1]]
# respostas esperadas
t = [1,1,1,-1]
# bias (ajuste fino)
b=0
#saida
y=0
# numero maximo de interacoes
max_int = 10
# taxa de aprendizado
taxa_aprendizado = 1
#soma
soma = 0
#theshold
threshold = 1
# nome do animal
animal = ""
# resposta = acerto ou falha
resposta = ""
# dicionario de dados
d = {'-1,-1,1,1' : 'cao',
'1,1,1,1' : 'gato',
PRÁTICA E LABORATÓRIO II 30
'1,1,-1,1' : 'cavalo',
'-1,-1,-1,1' : 'homem' }
# inicio do algoritmo
for k in range(1,max_int):
acertos = 0
print("INTERACAO "+str(k)+"-------------------------")
for i in range(0,len(x)):
soma = 0
PRÁTICA E LABORATÓRIO II 31
# a saida eh igual a adicao do bias com a soma anterior
y_in = b + soma
#print("y_in = ",str(y_in))
#imprime a resposta
if y == 1:
print(animal+" = quadrupede = "+resposta)
elif y == 0:
print(animal+" = padrao nao identificado = "+resposta)
elif y == -1:
print(animal+" = bipede = "+resposta)
if acertos == len(x):
PRÁTICA E LABORATÓRIO II 32
print("\nFuncionalidade aprendida com "+str(k)+" interacoes")
break;
print("")
print("\nFinalizado com Sucesso")
raw_input( )
Assim como o perceptron, deve-se somar os produtos de suas entradas com seus
respectivos pesos. Observe o código Phyton a seguir:
#!/usr/bin/env python
PRÁTICA E LABORATÓRIO II 33
# -*- coding: utf-8 -*-
# [0,0] | resposta = 0
# [0,1] | resposta = 1
# [1,0] | resposta = 1
# [1,1] | resposta = 1
# threshold (limiar)
threshold = 0
# peso 0
w_0 = -threshold
# entrada 0
x_0 = 1
# entradas
x = [[x_0,0,0],
[x_0,0,1],
[x_0,1,0],
[x_0,1,1]]
PRÁTICA E LABORATÓRIO II 34
qtde_itens_x = len(x[0])
# pesos (sinapses)
w = [w_0,0,0]
# respostas desejadas
d = [0,1,1,1]
#saida
y=0
# soma
u=0
#erro
e=0
# inicio do algoritmo
for k in range(1,max_int):
acertos = 0
PRÁTICA E LABORATÓRIO II 35
e=0
print("INTERACAO "+str(k)+"-------------------------")
for t in range(0,tamanho_x):
u=0
# funcao de saida
if u > 0:
y=1
else:
y=0
PRÁTICA E LABORATÓRIO II 36
if acertos == tamanho_x:
print("\nFuncionalidade aprendida com "+str(k)+" interacoes")
print("\nPesos encontrados =============== ")
for j in range (0,tamanho_w):
print(w[j])
break;
print("")
print("Finalizado")
raw_input( )
PRÁTICA E LABORATÓRIO II 37
2.8 Backpropagation
Uma das opções de redes neurais artificiais é trabalhar com o famoso algoritmo de
backpropagation, cujas principais vantagens é trabalhar com multicamadas e
resolver problemas “não linearmente separáveis” que alguns algoritmos não resolvem.
import math
import random
import string
class NN:
def __init__(self, NI, NH, NO):
PRÁTICA E LABORATÓRIO II 38
# number of nodes in layers
self.ni = NI + 1 # +1 for bias
self.nh = NH
self.no = NO
# initialize node-activations
self.ai, self.ah, self.ao = [],[], []
self.ai = [1.0]*self.ni
self.ah = [1.0]*self.nh
self.ao = [1.0]*self.no
for i in range(self.ni-1):
self.ai[i] = inputs[i]
for j in range(self.nh):
sum = 0.0
for i in range(self.ni):
PRÁTICA E LABORATÓRIO II 39
sum +=( self.ai[i] * self.wi[i][j] )
self.ah[j] = sigmoid (sum)
for k in range(self.no):
sum = 0.0
for j in range(self.nh):
sum +=( self.ah[j] * self.wo[j][k] )
self.ao[k] = sigmoid (sum)
return self.ao
PRÁTICA E LABORATÓRIO II 40
for j in range(self.nh):
error = 0.0
for k in range(self.no):
error += output_deltas[k] * self.wo[j][k]
hidden_deltas[j] = error * dsigmoid(self.ah[j])
def weights(self):
print 'Input weights:'
for i in range(self.ni):
print self.wi[i]
print
print 'Output weights:'
for j in range(self.nh):
print self.wo[j]
print ''
PRÁTICA E LABORATÓRIO II 41
def test(self, patterns):
for p in patterns:
inputs = p[0]
print 'Inputs:', p[0], '-->', self.runNN(inputs), '\tTarget', p[1]
PRÁTICA E LABORATÓRIO II 42
m.append([fill]*J)
return m
if __name__ == "__main__":
main()
raw_input( )
PRÁTICA E LABORATÓRIO II 43
3. Processamento de Linguagem Natural
Quando cientistas de dados têm que criar nuvens de palavras, em linhas gerais, devem
pensar se querem fazer os eixos transmitirem alguma coisa com algum sentido lógico.
Grus (2016, p. 239) cita um exemplo interessante quando supõe que para cada coleção
de dados de jargões relacionados à ciência você tenha dois números entre 0 e 100 –
o primeiro representando a frequência com que ele aparece em postagens de
empregos, e o segundo a frequência com que aparece em currículos:
data = [ ("big data", 100, 15), ("Hadoop", 95, 25), ("Python", 75, 50),
("R", 50, 40), ("machine learning", 80, 20), ("statistics", 20, 60),
("data science", 60, 70), ("analytics", 90, 3),
("team player", 85, 85), ("dynamic", 2, 90), ("synergies", 70, 0),
PRÁTICA E LABORATÓRIO II 44
("actionable insights", 40, 30), ("think out of the box", 45, 10),
("self-starter", 30, 50), ("customer focus", 65, 15),
("thought leadership", 35, 35)]
O interessante sobre nuvens de palavras é que elas têm uma abordagem de dispersão
dessas palavras para que a posição horizontal possa indicar a popularidade de
postagens, e a vertical, a popularidade de currículos, o que certamente, produziria
uma visualização que transmitiria alguns insights.
PRÁTICA E LABORATÓRIO II 45
def text_size(total):
"""equals 8 if total is 0, 28 if total is 200"""
return 8 + total / 200 * 20
Dessa forma, teríamos uma nuvem de palavras com palavras mais significativas,
embora aparentemente fosse menos atrativa.
Grus (2016) apresenta uma situação como exemplo para adentrar no estudo de
modelos de n-gramas. Vamos a ela:
“A vice-presidente de marketing de pesquisa quer que você crie milhares de páginas
Web sobre Data Science para que seu site seja classificado no topo dos resultados de
pesquisa para os termos relacionados”. Na verdade, ela não quer escrever milhares de
PRÁTICA E LABORATÓRIO II 46
páginas Web. Em vez disso, ela pergunta se você pode, de alguma forma, gerar estas
páginas.
O primeiro está relacionado aos apóstrofos no texto que, são representados pelo
caractere Unicode u”\u2019”. Dessa forma, há necessidade de se criar uma função
auxiliar para substituí-las por apóstrofos normais.
# n-gram models
def fix_unicode(text):
return text.replace(u"\u2019", "'")
O segundo problema está relacionado com o texto da página Web, pois devemos
dividi-lo em sequências de palavras e pontos para que possamos dizer onde se inicia
e termina uma sentença. Podemos fazer isto usando a função findall( ) do módulo
re:
document = []
PRÁTICA E LABORATÓRIO II 47
for paragraph in content("p"):
words = re.findall(regex, fix_unicode(paragraph.text))
document.extend(words)
return document
Certamente, você, como cientista de dados, poderia e deveria limpar um pouco mais
esses dados. Ainda existe uma grande quantidade de textos extrínsecos no
documento.
Agora que o texto disponível é uma sequência de palavras, podemos modelar uma
linguagem da seguinte forma: dada alguma palavra inicial, procura-se a partir de todas
as demais palavras, nos documentos-fonte, a próxima que nos interessa, de acordo
com a nossa necessidade. A partir daí, deve-se escolher aleatoriamente uma dessas
palavras para ser, portanto, a próxima palavra, e assim por diante, até que cheguemos
ao ponto, que expressa o final da sentença. Tecnicamente, essa técnica é denominada
modelo bigrama e pode ser determinada completamente por sequências de
bigramas nos dados originais.
Pode surgir a seguinte dúvida: por qual palavra começar? Deve-se começar a computar
as possíveis transições de palavras. Observe o trecho de código a seguir:
def generate_using_bigrams(transitions):
PRÁTICA E LABORATÓRIO II 48
current = "." # a próxima palavra sera uma sentenca
result = []
while True:
next_word_candidates = transitions[current] # bigramas
current = random.choice(next_word_candidates)
# escolhe um de forma aleatória
result.append(current) # anexa aos resultados
if current == ".": return " ".join(result)
# se "." então terminamos
As sentenças que produz são “besteiras”, mas são o tipo de bobagem que você deveria
colocar no seu web site, se está tentando fazer parecer com Data Science.
3.3 Gramáticas
grammar = {
"_S" : ["_NP _VP"],
"_NP" : ["_N",
"_A _NP _P _A _N"],
"_VP" : ["_V",
"_V _NP"],
"_N" : ["data science", "Python", "regression"],
"_A" : ["big", "linear", "logistic"],
"_P" : ["about", "near"],
"_V" : ["learns", "trains", "tests", "is"]
}
PRÁTICA E LABORATÓRIO II 49
Depois de tudo, sentenças poderão ser geradas com base na gramática a partir de
então.
def generate_sentence(grammar):
return expand(grammar, [“_S”])
As gramáticas são mais interessantes quando usadas em outra direção. Assim, dada
uma sentença, podemos usar uma gramática para analisá-la. Isso permite que
possamos identificar sujeitos e verbos que nos auxiliarão a compreender a sentença.
Utilizar ciência de dados para gerar textos é um truque esperto; usá-las para entender
o texto é mais esperto ainda.
Grus (2016) afirma que gerar abordagens de algumas distribuições é fácil. Devemos
seguir variáveis aleatórias e uniformes. No entanto, algumas distribuições são mais
difíceis de criar amostras.
A amostragem de Gibbs nada mais é que uma técnica para gerar amostras de
distribuição multidimensionais quando apenas conhecemos algumas das distribuições
condicionais. Observe um trecho de código Phyton com tal abordagem:
def direct_sample():
d1 = roll_a_die()
d2 = roll_a_die()
return d1, d1 + d2
PRÁTICA E LABORATÓRIO II 50
def random_y_given_x(x):
"""equally likely to be x + 1, x + 2, ... , x + 6"""
return x + roll_a_die()
def random_x_given_y(y):
if y <= 7:
# se o total for 7 ou menos, o primeiro dado e igualmente
# 1, 2, ..., (total - 1)
return random.randrange(1, y)
else:
# se o total for 7 ou mais, o primeiro dado e igualmente
# (total - 6), (total - 5), ..., 6
return random.randrange(y - 6, 7)
def gibbs_sample(num_iters=100):
x, y = 1, 2 # doesn't really matter
for _ in range(num_iters):
x = random_x_given_y(y)
y = random_y_given_x(x)
return x, y
def compare_distributions(num_samples=1000):
counts = defaultdict(lambda: [0, 0])
for _ in range(num_samples):
counts[gibbs_sample()][0] += 1
counts[direct_sample()][1] += 1
return counts
PRÁTICA E LABORATÓRIO II 51
por um valor aleatório escolhido condicionado a y por um valor aleatório escolhido a
x.
Os tópicos precisam ser definidos pelo cientista de dados antes de mais nada. Será
necessária então uma função para escolher aleatoriamente um índice baseado num
conjunto arbitrário de pesos.
# TOPIC MODELING
def sample_from(weights):
total = sum(weights)
rnd = total * random.random() # uniform entre 0 e total
for i, w in enumerate(weights):
rnd -= w # retorna o menor i tal que
if rnd <= 0: return i # sum(weights[:(i+1)]) >= rnd
Nossos documentos são os interesses de nossos usuários, que podem ser definidos,
por exemplo, como:
documents = [
["Hadoop", "Big Data", "HBase", "Java", "Spark", "Storm", "Cassandra"],
["NoSQL", "MongoDB", "Cassandra", "HBase", "Postgres"],
["Python", "scikit-learn", "scipy", "numpy", "statsmodels", "pandas"],
["R", "Python", "statistics", "regression", "probability"],
["machine learning", "regression", "decision trees", "libsvm"],
["Python", "R", "Java", "C++", "Haskell", "programming languages"],
["statistics", "probability", "mathematics", "theory"],
["machine learning", "scikit-learn", "Mahout", "neural networks"],
["neural networks", "deep learning", "Big Data", "artificial intelligence"],
["Hadoop", "Java", "MapReduce", "Big Data"],
["statistics", "R", "statsmodels"],
PRÁTICA E LABORATÓRIO II 52
["C++", "deep learning", "artificial intelligence", "probability"],
["pandas", "R", "Python"],
["databases", "HBase", "Postgres", "MySQL", "MongoDB"],
["libsvm", "regression", "support vector machines"]
]
def text_size(total):
"""equals 8 if total is 0, 28 if total is 200"""
return 8 + total / 200 * 20
PRÁTICA E LABORATÓRIO II 53
size=text_size(job_popularity + resume_popularity))
plt.xlabel("Popularity on Job Postings")
plt.ylabel("Popularity on Resumes")
plt.axis([0, 100, 0, 100])
plt.show()
#
# n-gram models
#
def fix_unicode(text):
return text.replace(u"\u2019", "'")
def get_document():
url = "http://radar.oreilly.com/2010/06/what-is-data-science.html"
html = requests.get(url).text
soup = BeautifulSoup(html, 'html5lib')
document = []
return document
PRÁTICA E LABORATÓRIO II 54
def generate_using_bigrams(transitions):
current = "." # this means the next word will start a sentence
result = []
while True:
next_word_candidates = transitions[current] # bigrams (current, _)
current = random.choice(next_word_candidates) # choose one at
random
result.append(current) # append it to results
if current == ".": return " ".join(result) # if "." we're done
if current == ".":
return " ".join(result)
def is_terminal(token):
return token[0] != "_"
# ignore terminals
PRÁTICA E LABORATÓRIO II 55
if is_terminal(token): continue
if is_terminal(replacement):
tokens[i] = replacement
else:
tokens = tokens[:i] + replacement.split() + tokens[(i+1):]
return expand(grammar, tokens)
def generate_sentence(grammar):
return expand(grammar, ["_S"])
#
# Gibbs Sampling
#
def roll_a_die():
return random.choice([1,2,3,4,5,6])
def direct_sample():
d1 = roll_a_die()
d2 = roll_a_die()
return d1, d1 + d2
def random_y_given_x(x):
"""equally likely to be x + 1, x + 2, ... , x + 6"""
PRÁTICA E LABORATÓRIO II 56
return x + roll_a_die()
def random_x_given_y(y):
if y <= 7:
# if the total is 7 or less, the first die is equally likely to be
# 1, 2, ..., (total - 1)
return random.randrange(1, y)
else:
# if the total is 7 or more, the first die is equally likely to be
# (total - 6), (total - 5), ..., 6
return random.randrange(y - 6, 7)
def gibbs_sample(num_iters=100):
x, y = 1, 2 # doesn't really matter
for _ in range(num_iters):
x = random_x_given_y(y)
y = random_y_given_x(x)
return x, y
def compare_distributions(num_samples=1000):
counts = defaultdict(lambda: [0, 0])
for _ in range(num_samples):
counts[gibbs_sample()][0] += 1
counts[direct_sample()][1] += 1
return counts
#
# TOPIC MODELING
#
def sample_from(weights):
PRÁTICA E LABORATÓRIO II 57
total = sum(weights)
rnd = total * random.random() # uniform between 0 and total
for i, w in enumerate(weights):
rnd -= w # return the smallest i such that
if rnd <= 0: return i # sum(weights[:(i+1)]) >= rnd
documents = [
["Hadoop", "Big Data", "HBase", "Java", "Spark", "Storm", "Cassandra"],
["NoSQL", "MongoDB", "Cassandra", "HBase", "Postgres"],
["Python", "scikit-learn", "scipy", "numpy", "statsmodels", "pandas"],
["R", "Python", "statistics", "regression", "probability"],
["machine learning", "regression", "decision trees", "libsvm"],
["Python", "R", "Java", "C++", "Haskell", "programming languages"],
["statistics", "probability", "mathematics", "theory"],
["machine learning", "scikit-learn", "Mahout", "neural networks"],
["neural networks", "deep learning", "Big Data", "artificial intelligence"],
["Hadoop", "Java", "MapReduce", "Big Data"],
["statistics", "R", "statsmodels"],
["C++", "deep learning", "artificial intelligence", "probability"],
["pandas", "R", "Python"],
["databases", "HBase", "Postgres", "MySQL", "MongoDB"],
["libsvm", "regression", "support vector machines"]
]
K=4
document_topic_counts = [Counter()
for _ in documents]
PRÁTICA E LABORATÓRIO II 58
topic_counts = [0 for _ in range(K)]
D = len(documents)
PRÁTICA E LABORATÓRIO II 59
return sample_from([topic_weight(d, word, k)
for k in range(K)])
random.seed(0)
document_topics = [[random.randrange(K) for word in document]
for document in documents]
for d in range(D):
for word, topic in zip(documents[d], document_topics[d]):
document_topic_counts[d][topic] += 1
topic_word_counts[topic][word] += 1
topic_counts[topic] += 1
PRÁTICA E LABORATÓRIO II 60
document_topic_counts[d][new_topic] += 1
topic_word_counts[new_topic][word] += 1
topic_counts[new_topic] += 1
document_lengths[d] += 1
if __name__ == "__main__":
document = get_document()
random.seed(0)
print "bigram sentences"
for i in range(10):
print i, generate_using_bigrams(transitions)
print
# trigrams
PRÁTICA E LABORATÓRIO II 61
trigram_transitions[(prev, current)].append(next)
grammar = {
"_S" : ["_NP _VP"],
"_NP" : ["_N",
"_A _NP _P _A _N"],
"_VP" : ["_V",
"_V _NP"],
"_N" : ["data science", "Python", "regression"],
"_A" : ["big", "linear", "logistic"],
"_P" : ["about", "near"],
"_V" : ["learns", "trains", "tests", "is"]
}
# topic MODELING
PRÁTICA E LABORATÓRIO II 62
for k, word_counts in enumerate(topic_word_counts):
for word, count in word_counts.most_common():
if count > 0: print k, word, count
PRÁTICA E LABORATÓRIO II 63
A partir de um paradigma inspirado em primitivas de programação funcional, foi criado
um framework que permite a manipulação de grande volume de dados de forma
paralela e distribuída, além de prover tolerância à falha, escalonamento de I/O e
monitoramento.
Para cara palavra do documento de entrada, a função map emite o valor ‘1’ associado
à chave que representa a palavra em questão. A função de reduce soma todas as
contagens emitidas para uma mesma chave, ou seja, uma mesma palavra.
def word_count_old(documents):
"""word count not using MapReduce"""
return Counter(word
for document in documents
for word in tokenize(document))
PRÁTICA E LABORATÓRIO II 65
def wc_mapper(document):
"""for each word in the document, emit (word,1)"""
for word in tokenize(document):
yield (word, 1)
def word_count(documents):
"""count the words in the input documents using MapReduce"""
return [output
for word, counts in collector.iteritems()
for output in wc_reducer(word, counts)]
PRÁTICA E LABORATÓRIO II 66
return [output
for key, values in collector.iteritems()
for output in reducer(key,values)]
def values_reducer(aggregation_fn):
"""turns a function (values -> output) into a reducer"""
return partial(reduce_with, aggregation_fn)
sum_reducer = values_reducer(sum)
max_reducer = values_reducer(max)
min_reducer = values_reducer(min)
count_distinct_reducer = values_reducer(lambda values: len(set(values)))
#
# Analyzing Status Updates
#
status_updates = [
{"id": 1,
"username" : "joelgrus",
"text" : "Is anyone interested in a data science book?",
"created_at" : datetime.datetime(2013, 12, 21, 11, 47, 0),
"liked_by" : ["data_guy", "data_gal", "bill"] },
# add your own
]
def data_science_day_mapper(status_update):
PRÁTICA E LABORATÓRIO II 67
"""yields (day_of_week, 1) if status_update contains "data science" """
if "data science" in status_update["text"].lower():
day_of_week = status_update["created_at"].weekday()
yield (day_of_week, 1)
data_science_days = map_reduce(status_updates,
data_science_day_mapper,
sum_reducer)
def words_per_user_mapper(status_update):
user = status_update["username"]
for word in tokenize(status_update["text"]):
yield (user, (word, 1))
word_counts = Counter()
for word, count in words_and_counts:
word_counts[word] += count
user_words = map_reduce(status_updates,
words_per_user_mapper,
most_popular_word_reducer)
def liker_mapper(status_update):
PRÁTICA E LABORATÓRIO II 68
user = status_update["username"]
for liker in status_update["liked_by"]:
yield (user, liker)
distinct_likers_per_user = map_reduce(status_updates,
liker_mapper,
count_distinct_reducer)
#
# matrix multiplication
#
if matrix == "A":
for column in range(m):
# A_ij is the jth entry in the sum for each C_i_column
yield((i, column), (j, value))
else:
for row in range(m):
# B_ij is the ith entry in the sum for each C_row_j
yield((row, j), (i, value))
PRÁTICA E LABORATÓRIO II 69
# sum up all the products of the positions with two results
sum_product = sum(results[0] * results[1]
for results in results_by_index.values()
if len(results) == 2)
if sum_product != 0.0:
yield (key, sum_product)
if __name__ == "__main__":
wc_mapper_results = [result
for document in documents
for result in wc_mapper(document)]
PRÁTICA E LABORATÓRIO II 70
print
# matrix multiplication
raw_input( )
PRÁTICA E LABORATÓRIO II 71
A operação deverá ser realiza a partir de um a plataforma de software especial
denominada Hadoop.
PRÁTICA E LABORATÓRIO II 72
Todos os módulos do Hadoop são desenhados com a premissa fundamental de que
falhas em hardware são comuns, sejam elas máquinas individuais ou um conjunto
inteiro de máquinas em racks, e devem, portanto, ser automaticamente tratadas por
software pelo framework.
A partir de diversas redes sociais, como Facebook, Instagram, Linkedin, Twitter etc.,
pode-se buscar esses possíveis vínculos a fim de se analisar dados a partir da rede
mundial de computadores.
PRÁTICA E LABORATÓRIO II 73
Então, já temos maquinário suficiente para fazer outras abordagens em rede.
Lembre-se de que a rede engloba diversos usuários:
users = [
{ “id”: 0, “name”: “Hero” },
{ “id”: 1, “name”: “Dunn” },
{ “id”: 2, “name”: “Sue” },
{ “id”: 3, “name”: “Chi” },
{ “id”: 4, “name”: “Thor” },
{ “id”: 5, “name”: “Clive” },
{ “id”: 6, “name”: “Hicks” },
{ “id”: 7, “name”: “Devin” },
{ “id”: 8, “name”: “Keite” },
{ “id”: 9, “name”: “Klein” }
]
E também amizades:
friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (3, 4), (4, 5), (5, 6), (5, 7),
(6, 8), (7, 8), (8, 9)]
PRÁTICA E LABORATÓRIO II 74
A figura reporta, portanto, a rede social de cientistas de dados DataSciencester. Além
disso, também adicionamos listas de amigos para cada dict de usuário:
for i, j in friendships:
users[i][“friends”].append(users[j])
#adiciona i como amigo de j
users[j][“friends”].append(users[i])
#adiciona j como amigo de i
PRÁTICA E LABORATÓRIO II 75
4.2 Centralidade de vetor próprio
Grus (2016, p.260) afirma que para falar de centralidade de vetor próprio é necessário
falar sobre vetores próprios, e para falar sobre vetores próprios temos que falar sobre
multiplicidade de matrizes.
n = len(users)
adjacency_matrix = make_matrix(n, n, entry_fn)
PRÁTICA E LABORATÓRIO II 77
Pode-se observar que os usuários 1 e 2 são os mais centrais, pois ambos possuem
três conexões com pessoas que são altamente centrais. Dessa forma, conforme nos
afastamos deles, as centralidades das pessoas gradualmente diminuem.
De acordo com Grus (2016, p. 264), DataSciencester não está conseguindo deslanchar
conforme foi previsto. Então, o vice-presidente de rendimentos considera a troca de
um modelo de amizade por um modelo de aprovação.
endorsements = [(0, 1), (1, 0), (0, 2), (2, 0), (1, 2), (2, 1), (1, 3),
(2, 3), (3, 4), (5, 4), (5, 6), (7, 5), (6, 8), (8, 7), (8, 9)]
Uma métrica melhor para se levar em consideração é quem aprova você. Segundo
Grus (2016), aprovações de pessoas com muitas aprovações deveriam de alguma
forma contar mais do que as aprovações de pessoas com poucas aprovações. Esta é
a essência do algoritmo PageRank, usado pelo Google para ordenar web sites
baseados em quais outros sites estão conectados a eles e assim por diante.
for __ in range(num_iters):
next_pr = { user["id"] : base_pr for user in users }
for user in users:
# distribui PageRank para links de saida
links_pr = pr[user["id"]] * damping
for endorsee in user["endorses"]:
next_pr[endorsee["id"]] += links_pr / len(user["endorses"])
pr = next_pr
return pr
PRÁTICA E LABORATÓRIO II 79
Na rede DataSciencester ilustrada anteriormente, o algoritmo PageRank identifica o
usuário número 4 (Thor) como o cientista de dados com o maior número de
classificações.
Dessa forma, mesmo que ele tenha menos aprovações do que os usuários 0, 1 e 2, as
aprovações dele carregam classificações de suas aprovações.
# Analise de Rede
from __future__ import division
import math, random, re
from collections import defaultdict, Counter, deque
from linear_algebra import dot, get_row, get_column, make_matrix,
magnitude, scalar_multiply, shape, distance
from functools import partial
users = [
{ "id": 0, "name": "Hero" },
{ "id": 1, "name": "Dunn" },
{ "id": 2, "name": "Sue" },
{ "id": 3, "name": "Chi" },
{ "id": 4, "name": "Thor" },
{ "id": 5, "name": "Clive" },
PRÁTICA E LABORATÓRIO II 80
{ "id": 6, "name": "Hicks" },
{ "id": 7, "name": "Devin" },
{ "id": 8, "name": "Kate" },
{ "id": 9, "name": "Klein" }
]
friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (3, 4),
(4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)]
# and populate it
for i, j in friendships:
# this works because users[i] is the user whose id is i
users[i]["friends"].append(users[j]) # add i as a friend of j
users[j]["friends"].append(users[i]) # add j as a friend of i
#
# Betweenness Centrality
#
def shortest_paths_from(from_user):
PRÁTICA E LABORATÓRIO II 81
for friend in from_user["friends"])
# the fact that we're pulling from our queue means that
# necessarily we already know a shortest path to prev_user
paths_to_prev = shortest_paths_to[prev_user["id"]]
paths_via_prev = [path + [user_id] for path in paths_to_prev]
shortest_paths_to[user_id] = old_paths_to_here +
new_paths_to_here
PRÁTICA E LABORATÓRIO II 82
# add new neighbors to the frontier
frontier.extend((user, friend)
for friend in user["friends"]
if friend["id"] not in shortest_paths_to)
return shortest_paths_to
#
# closeness centrality
#
def farness(user):
"""the sum of the lengths of the shortest paths to each other user"""
return sum(len(paths[0])
PRÁTICA E LABORATÓRIO II 83
for paths in user["shortest_paths"].values())
#
# matrix multiplication
#
def vector_as_matrix(v):
"""returns the vector v (represented as a list) as a n x 1 matrix"""
return [[v_i] for v_i in v]
def vector_from_matrix(v_as_matrix):
"""returns the n x 1 matrix as a list of values"""
return [row[0] for row in v_as_matrix]
PRÁTICA E LABORATÓRIO II 84
product = matrix_multiply(A, v_as_matrix)
return vector_from_matrix(product)
while True:
result = matrix_operate(A, guess)
length = magnitude(result)
next_guess = scalar_multiply(1/length, result)
guess = next_guess
#
# eigenvector centrality
#
n = len(users)
adjacency_matrix = make_matrix(n, n, entry_fn)
eigenvector_centralities, _ = find_eigenvector(adjacency_matrix)
#
# directed graphs
#
PRÁTICA E LABORATÓRIO II 85
endorsements = [(0, 1), (1, 0), (0, 2), (2, 0), (1, 2), (2, 1), (1, 3),
(2, 3), (3, 4), (5, 4), (5, 6), (7, 5), (6, 8), (8, 7), (8, 9)]
sorted(endorsements_by_id,
key=lambda (user_id, num_endorsements): num_endorsements,
reverse=True)
for __ in range(num_iters):
PRÁTICA E LABORATÓRIO II 86
next_pr = { user["id"] : base_pr for user in users }
for user in users:
# distribute PageRank to outgoing links
links_pr = pr[user["id"]] * damping
for endorsee in user["endorses"]:
next_pr[endorsee["id"]] += links_pr / len(user["endorses"])
pr = next_pr
return pr
if __name__ == "__main__":
print "PageRank"
for user_id, pr in page_rank(users).iteritems():
print user_id, pr
PRÁTICA E LABORATÓRIO II 87
raw_input( )
users_interests = [
["Hadoop", "Big Data", "HBase", "Java", "Spark", "Storm", "Cassandra"],
PRÁTICA E LABORATÓRIO II 88
["NoSQL", "MongoDB", "Cassandra", "HBase", "Postgres"],
["Python", "scikit-learn", "scipy", "numpy", "statsmodels", "pandas"],
["R", "Python", "statistics", "regression", "probability"],
["machine learning", "regression", "decision trees", "libsvm"],
["Python", "R", "Java", "C++", "Haskell", "programming languages"],
["statistics", "probability", "mathematics", "theory"],
["machine learning", "scikit-learn", "Mahout", "neural networks"],
["neural networks", "deep learning", "Big Data", "artificial intelligence"],
["Hadoop", "Java", "MapReduce", "Big Data"],
["statistics", "R", "statsmodels"],
["C++", "deep learning", "artificial intelligence", "probability"],
["pandas", "R", "Python"],
["databases", "HBase", "Postgres", "MySQL", "MongoDB"],
["libsvm", "regression", "support vector machines"]
]
Uma abordagem fácil para isto é simplesmente recomendar aquilo que é considerado
popular:
popular_interests = Counter(interest
for user_interests in users_interests
for interest in user_interests).most_common()
Que se parece com alguma coisa que já tenhamos pensado ou necessitado um dia:
[(‘Phyton’, 4),
(‘R’, 4),
(‘Java’, 3),
(‘regression’, 3),
(‘statistics’, 3),
(‘propability’, 3),
PRÁTICA E LABORATÓRIO II 89
# ...
]
Para tanto, precisaremos de uma forma de medição para saber quão similares os dois
usuários são. Então, utilizaremos uma métrica chamada similaridade do cosseno,
conforme ilustração do gráfico a seguir:
Inicialmente, deve-se transpor a matriz de interesse do nosso usuário para que linhas
correspondam a interesses e colunas correspondam a usuários.
interest_user_matrix = [[user_interest_vector[j]
for user_interest_vector in user_interest_matrix]
for j, _ in enumerate(unique_interests)]
Seu funcionamento está relacionado a usuários com interesse e a outros sem nenhum
interesse. Por exemplo, unique_interests[0] é Big Data e
interest_user_matrix[0] também é:
[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0]
# Sistemas Recomendadores
from __future__ import division
import math, random
from collections import defaultdict, Counter
from linear_algebra import dot
users_interests = [
["Hadoop", "Big Data", "HBase", "Java", "Spark", "Storm", "Cassandra"],
["NoSQL", "MongoDB", "Cassandra", "HBase", "Postgres"],
["Python", "scikit-learn", "scipy", "numpy", "statsmodels", "pandas"],
["R", "Python", "statistics", "regression", "probability"],
["machine learning", "regression", "decision trees", "libsvm"],
["Python", "R", "Java", "C++", "Haskell", "programming languages"],
["statistics", "probability", "mathematics", "theory"],
["machine learning", "scikit-learn", "Mahout", "neural networks"],
["neural networks", "deep learning", "Big Data", "artificial intelligence"],
["Hadoop", "Java", "MapReduce", "Big Data"],
["statistics", "R", "statsmodels"],
["C++", "deep learning", "artificial intelligence", "probability"],
["pandas", "R", "Python"],
PRÁTICA E LABORATÓRIO II 92
["databases", "HBase", "Postgres", "MySQL", "MongoDB"],
["libsvm", "regression", "support vector machines"]
]
popular_interests = Counter(interest
for user_interests in users_interests
for interest in user_interests).most_common()
#
# user-based filtering
#
def make_user_interest_vector(user_interests):
"""given a list of interests, produce a vector whose i-th element is 1
if unique_interests[i] is in the list, 0 otherwise"""
return [1 if interest in user_interests else 0
for interest in unique_interests]
PRÁTICA E LABORATÓRIO II 93
user_interest_matrix = map(make_user_interest_vector, users_interests)
user_similarities = [[cosine_similarity(interest_vector_i,
interest_vector_j)
for interest_vector_j in user_interest_matrix]
for interest_vector_i in user_interest_matrix]
def most_similar_users_to(user_id):
pairs = [(other_user_id, similarity) # find other
for other_user_id, similarity in # users with
enumerate(user_similarities[user_id]) # nonzero
if user_id != other_user_id and similarity > 0] # similarity
PRÁTICA E LABORATÓRIO II 94
if include_current_interests:
return suggestions
else:
return [(suggestion, weight)
for suggestion, weight in suggestions
if suggestion not in users_interests[user_id]]
#
# Item-Based Collaborative Filtering
#
interest_user_matrix = [[user_interest_vector[j]
for user_interest_vector in user_interest_matrix]
for j, _ in enumerate(unique_interests)]
def most_similar_interests_to(interest_id):
similarities = interest_similarities[interest_id]
pairs = [(unique_interests[other_interest_id], similarity)
for other_interest_id, similarity in enumerate(similarities)
if interest_id != other_interest_id and similarity > 0]
return sorted(pairs,
key=lambda (_, similarity): similarity,
reverse=True)
PRÁTICA E LABORATÓRIO II 95
for interest_id, is_interested in enumerate(user_interest_vector):
if is_interested == 1:
similar_interests = most_similar_interests_to(interest_id)
for interest, similarity in similar_interests:
suggestions[interest] += similarity
suggestions = sorted(suggestions.items(),
key=lambda (_, similarity): similarity,
reverse=True)
if include_current_interests:
return suggestions
else:
return [(suggestion, weight)
for suggestion, weight in suggestions
if suggestion not in users_interests[user_id]]
if __name__ == "__main__":
PRÁTICA E LABORATÓRIO II 96
print "already like:", ["R", "Python", "statistics", "regression",
"probability"]
print most_popular_new_interests(["R", "Python", "statistics",
"regression", "probability"])
print
PRÁTICA E LABORATÓRIO II 97
Referências
CORRAR, Luiz J.; PAULO, Edilson; DIAS FILHO, José Maria. et al. (Coordenadores).
Análise multivariada para os cursos de administração, ciências contábeis e
economia. SãoPaulo: Atlas, 2007.
DAVENPORT, Thomas Hayes; PATIL, Dhanurjay. Data Scientist: The Sexiest Job of the
21st Century, Harvard Business Review, October, 2012.
GRUS, Joel. Data science do zero: primeiras regras com o Phyton. Rio de Janeiro:
Alta Books, 2016.
PROVOST, Foster; FAWCETT, Tom. Data science for business: what you nedd to
know about data mining and data-analytic thinking. [s./l.]: Spring, 2015.
PRÁTICA E LABORATÓRIO II 98