# 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 [3]:
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","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 [9]:
# EXERCICIO
import re
split_regex = r'\W+'
stopfile = os.path.join("Data","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
"""
str_list = re.split(split_regex, string)
str_list = filter(lambda w: len(w)>0, map(lambda w: w.lower(), str_list))
return [w for w in str_list if w not in stopwords]
wordsRDD = dataRDD.map(lambda x: tokenize(x[1]))
print (wordsRDD.take(1)[0])
In [10]:
# TEST Tokenize a String (1a)
assert wordsRDD.take(1)[0]==[u'quiet', u'introspective', u'entertaining', u'independent', u'worth', u'seeking'], 'lista incorreta!'
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 [13]:
# EXERCICIO
from pyspark.mllib.feature import Word2Vec
model = (Word2Vec()
.setVectorSize(5)
.setSeed(42)
.fit(wordsRDD))
print (model.transform(u'entertaining'))
print (list(model.findSynonyms(u'entertaining', 2)))
In [17]:
dist = np.abs(model.transform(u'entertaining')-np.array([0.0136831374839,0.00371457682922,-0.135785803199,0.047585401684,0.0414853096008])).mean()
assert dist<1e-6, 'valores incorretos'
assert list(model.findSynonyms(u'entertaining', 1))[0][0] == 'god', 'valores incorretos'
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 [36]:
# EXERCICIO
uniqueWords = (wordsRDD
.flatMap(lambda ws: [(w, 1) for w in ws])
.reduceByKey(lambda x,y: x+y)
.filter(lambda wf: wf[1]>=5)
.map(lambda wf: wf[0])
.collect()
)
print ('{} tokens únicos'.format(len(uniqueWords)))
w2v = {}
for w in uniqueWords:
w2v[w] = model.transform(w)
w2vb = sc.broadcast(w2v)
print ('Vetor entertaining: {}'.format( w2v[u'entertaining']))
vectorsRDD = (wordsRDD
.map(lambda ws: np.array([w2vb.value[w] for w in ws if w in w2vb.value]))
)
recs = vectorsRDD.take(2)
firstRec, secondRec = recs[0], recs[1]
print (firstRec.shape, secondRec.shape)
In [37]:
# TEST Tokenizing the small datasets (1c)
assert len(uniqueWords) == 3388, 'valor incorreto'
assert np.mean(np.abs(w2v[u'entertaining']-[0.0136831374839,0.00371457682922,-0.135785803199,0.047585401684,0.0414853096008]))<1e-6,'valor incorreto'
assert secondRec.shape == (10,5)
In [40]:
# EXERCICIO
from pyspark.mllib.clustering import KMeans
vectors2RDD = sc.parallelize(np.array(list(w2v.values())),1)
print ('Sample vector: {}'.format(vectors2RDD.take(1)))
modelK = KMeans.train(vectors2RDD, 200, seed=42)
clustersRDD = vectors2RDD.map(lambda x: modelK.predict(x))
print ('10 first clusters allocation: {}'.format(clustersRDD.take(10)))
In [41]:
# TEST Amazon record with the most tokens (1d)
assert clustersRDD.take(10)==[142, 83, 42, 0, 87, 52, 190, 17, 56, 0], 'valor incorreto'
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 [43]:
# EXERCICIO
def quantizador(point, model, k, w2v):
key = point[0]
words = tokenize(point[1])
matrix = np.array( [w2v[w] for w in words if w in w2v] )
features = np.zeros(k)
for v in matrix:
c = model.predict(v)
features[c] += 1
return (key, features)
quantRDD = dataRDD.map(lambda x: quantizador(x, modelK, 500, w2v))
print (quantRDD.take(1))
In [44]:
# TEST Implement a TF function (2a)
assert quantRDD.take(1)[0][1].sum() == 5, 'valores incorretos'