# EXERCICIO
e os códigos a serem completados estão marcados pelos comentários <COMPLETAR>
."id da frase","id da sentença","Frase","Sentimento"
In [ ]:
import os
import numpy as np
def parseRDD(point):
""" Parser for the current dataset. It receives a data point and return
a sentence (third field).
Args:
point (str): input data point
Returns:
str: a string
"""
data = point.split('\t')
return (int(data[0]),data[2])
def notempty(point):
""" Returns whether the point string is not empty
Args:
point (str): input string
Returns:
bool: True if it is not empty
"""
return len(point[1])>0
filename = os.path.join("Data","Aula04","MovieReviews2.tsv")
rawRDD = sc.textFile(filename,100)
header = rawRDD.take(1)[0]
dataRDD = (rawRDD
#.sample(False, 0.1, seed=42)
.filter(lambda x: x!=header)
.map(parseRDD)
.filter(notempty)
#.sample( False, 0.1, 42 )
)
print 'Read {} lines'.format(dataRDD.count())
print 'Sample line: {}'.format(dataRDD.takeSample(False, 1)[0])
transform
para transformar cada token em uma representaçã vetorial.
In [ ]:
# EXERCICIO
import re
split_regex = r'\W+'
stopfile = os.path.join("Data","Aula04","stopwords.txt")
stopwords = set(sc.textFile(stopfile).collect())
def tokenize(string):
""" An implementation of input string tokenization that excludes stopwords
Args:
string (str): input string
Returns:
list: a list of tokens without stopwords
"""
return <COMPLETAR>
wordsRDD = dataRDD.map(lambda x: tokenize(x[1]))
print wordsRDD.take(1)[0]
In [ ]:
# TEST Tokenize a String (1a)
assert wordsRDD.take(1)[0]==[u'quiet', u'introspective', u'entertaining', u'independent', u'worth', u'seeking'], 'lista incorreta!'
print 'ok!'
fit
na RDD criada no exercício anterior.Word2Vec()
, em seguida aplicando o método setVectorSize()
com o tamanho que queremos para nosso vetor (utilize tamanho 5), seguido de setSeed()
para a semente aleatória, em caso de experimentos controlados (utilizaremos 42) e, finalmente, fit()
com nossa wordsRDD
como parâmetro.
In [ ]:
# EXERCICIO
from pyspark.mllib.feature import Word2Vec
model = Word2Vec().<COMPLETAR>
print model.transform(u'entertaining')
print model.findSynonyms(u'entertaining', 2)
In [ ]:
dist = np.abs(model.transform(u'entertaining')-np.array([-0.246186971664,-0.127226486802,0.0271916668862,0.0112947737798,-0.206053063273])).mean()
assert dist<1e-6, 'valores incorretos'
print 'ok!'
assert model.findSynonyms(u'entertaining', 1)[0][0] == 'affair', 'valores incorretos'
print 'ok!'
uniqueWords
contendo as palavras únicas do RDD words, removendo aquelas que aparecem menos do que 5 vezes $^1$. Em seguida, criaremos um dicionário w2v
que a chave é um token e o valor é um np.array
do vetor transformado daquele token$^2$.vectorsRDD
em que cada registro é representado por uma matriz onde cada linha representa uma palavra transformada.Na versão 1.3 do PySpark o modelo Word2Vec utiliza apenas os tokens que aparecem mais do que 5 vezes no corpus, na versão 1.4 isso é parametrizado.
Na versão 1.4 do PySpark isso pode ser feito utilizando o método `getVectors()
In [ ]:
# EXERCICIO
uniqueWords = (wordsRDD
.<COMPLETAR>
.<COMPLETAR>
.<COMPLETAR>
.<COMPLETAR>
.collect()
)
print '{} tokens únicos'.format(len(uniqueWords))
w2v = {}
for w in uniqueWords:
w2v[w] = <COMPLETAR>
w2vb = sc.broadcast(w2v)
print 'Vetor entertaining: {}'.format( w2v[u'entertaining'])
vectorsRDD = (wordsRDD
.<COMPLETAR>
)
recs = vectorsRDD.take(2)
firstRec, secondRec = recs[0], recs[1]
print firstRec.shape, secondRec.shape
In [ ]:
# TEST Tokenizing the small datasets (1c)
assert len(uniqueWords) == 3332, 'valor incorreto'
print 'ok!'
assert np.mean(np.abs(w2v[u'entertaining']-[-0.24618697, -0.12722649, 0.02719167, 0.01129477, -0.20605306]))<1e-6,'valor incorreto'
print 'ok!'
assert secondRec.shape == (10,5)
print 'ok!'
In [ ]:
# EXERCICIO
from pyspark.mllib.clustering import KMeans
vectors2RDD = sc.parallelize(np.array(w2v.values()),1)
print 'Sample vector: {}'.format(vectors2RDD.take(1))
modelK = KMeans.<COMPLETAR>
clustersRDD = vectors2RDD.<COMPLETAR>
print '10 first clusters allocation: {}'.format(clustersRDD.take(10))
In [ ]:
# TEST Amazon record with the most tokens (1d)
assert clustersRDD.take(10)==[134, 126, 209, 221, 401, 485, 197, 269, 296, 265], 'valor incorreto'
print 'ok'
tokenize
na string. Em seguida, transformamos a lista de tokens em uma matriz word2vec. Finalmente, aplicamos cada vetor dessa matriz no modelo de k-Means, gerando um vetor de tamanho $k$ em que cada posição $i$ indica quantos tokens pertencem ao cluster $i$.
In [ ]:
# EXERCICIO
def quantizador(point, model, k, w2v):
key = <COMPLETAR>
words = <COMPLETAR>
matrix = np.array( <COMPLETAR> )
features = np.zeros(k)
for v in matrix:
c = <COMPLETAR>
features[c] += 1
return (key, features)
quantRDD = dataRDD.map(lambda x: quantizador(x, modelK, 500, w2v))
print quantRDD.take(1)
In [ ]:
# TEST Implement a TF function (2a)
assert quantRDD.take(1)[0][1].sum() == 5, 'valores incorretos'
print 'ok!'
In [ ]:
dataNorms = quantRDD.map(lambda rec: (rec[0],np.sqrt(rec[1].dot(rec[1]))))
dataNormsBroadcast = sc.broadcast(dataNorms.collectAsMap())
cosineSim
que receberá um par ( (doc1, vec1), (doc2, vec2) ) para calcular a similaridade do cosseno entre esses dois documentos.genList
que deve gerar uma lista de tuplas (token, ((doc1,tfidf),(doc2,tfidf)) de todos os pares de documentos com essa token em comum exceto nos casos doc1==doc2
.
In [ ]:
# EXERCICIO
from itertools import product
def calcsim(rec):
items = list(rec[1])
return <COMPLETAR>
newRDD = (quantRDD
.<COMPLETAR>
.<COMPLETAR>
.<COMPLETAR>
.<COMPLETAR>
.<COMPLETAR>
.cache()
)
newcount = newRDD.count()
print newcount
In [ ]:
assert newcount==11796442, 'incorrect value'
print 'ok'
In [ ]:
# EXERCICIO
def genklist(rec,k):
""" Generate the list of the k most similar documents to the key
Args:
record: a pair, (doc, [(doc,sim)])
k: number of most similar elements
Returns:
pair: (doc, [(doc,sim)])
"""
<COMPLETAR>
return (key, docs[:k])
def knn(simRDD, k):
""" Generate the knn RDD for a given RDD.
Args:
simRDD: RDD of ( (doc1,doc2), sim)
k: number of most similar elements
Returns:
RDD: RDD of ( doc1, [docs, sims])
"""
ksimRDD = (simRDD
.<COMPLETAR>
.<COMPLETAR>
.<COMPLETAR>
)
return ksimRDD
ksimReviewsRDD = knn(newRDD, 3)
ksimReviewsRDD.take(3)
In [ ]:
print dataRDD.filter(lambda x: x[0] in [55300,39009,130973,66284]).collect()