Nem sei se vocês têm acompanhado minha saga mestradística por aqui pelas bandas das Coréia, mas lembram-se de quando eu comecei a estudar Python, comecei a fazer aqueles programinhas, estava arrancando meus cabelos para pensar em algum projeto... Pois é. Meus problemas acabaram!!! Com o Super-Auto-Programeitor Tabajara... ops! Canal errado! (Momento Idiocracy...) Voltando: meus problemas já se findaram graças a um belo trabalho de equipe que, pelo que percebi, ocorreu pela primeira vez em nossa "lindo" Laboratório de Lingüística (eita palavrinha difícil de escrever... eu sempre digito isso umas três vezes por causa dos acentos que saem nos lugares errados...) Computacional da Universidade Nacional de Seul, Coréia. Eu e Munhyong, meu colega de laboratório, resolvemos partir para o matadouro juntos. Munhyong estudou na Universidade de Línguas Estrangeiras da Coréia (韓國外國語大學校) no departamento de Engenharia (?) (não entendi isso até hoje... engenharia numa faculdade de línguas, mas tudo bem...) e sabe programar muito bem em C e adjacências. O problema é que C, para o que precisamos fazer é um pouco "muito complicado de mais", e geralmente fazemos uso de outras línguas de programação, principalmente Perl. Passamos o semestre passado fazendo programinhas em Perl para aprender (no estilo "sevirômetro") e acabamos manejando mais ou menos essa língua de programação meio esquisita mas muito útil. Aí vieram as férias, depois outras aulas e outros afazeres e agora, no final do semestre, quando ele foi fazer seus programinhas em Perl, descobriu que já tinha esquecido quase tudo.
No meu caso, descobri um "kit de ferramentas" para trabalhar com programação de processamento de línguas naturais chamado NLTK que tem por base a linguagem de programação chamada Python. Pra mim que já vivia no mundo GNU/Linux por mais de 3 anos, além de uns 5 anos de curioso antes disso, o nome Python não era em nada estranho. Além disso, eu já tinha até me aventurado a tentar fazer um programinha em Python pouco antes de entrar no mestrado, e resolvi unir o útil ao agradável: usar o NLTK e, de quebra, aprender mais uma lingüinha de programação. Vocês devem se lembrar de algum post anterior onde devo ter mencionado esse fato. De lá pra cá, mergulhei no Python e fui aprendendo na marra a usar essa língua muito estranha no começo (principalmente pra quem usava Perl) e absurdamente útil agora! Simplesmente não consigo me imaginar sem usar Python agora. Depois de pegar o jeito da coisa (e olha que eu nem comecei a arranhar a superfície ainda...), tudo fica bem mais fácil, prático e útil em uma bordoada só.
Voltando ao assunto do trabalho... Quando estava sofrendo em busca do cálice sagrado, a respeito do que poderia fazer como projeto final do curso de Lingüística Computacional 2, acabei comentando com o Munhyong e ele convidou-me a fazer o projeto com ele, já que ele tinha uma idéia meio Frankenstein de unir dois projetos que a gente havia estudado durante o curso. Pus-me então a ajudá-lo, seguindo suas instruções e fazendo meus programinhas. Não obstante o fato de que esforçamo-nos deveras, a primeira idéia acabou não dando muito certo. Sem perder as estribeiras, Munhyong acabou frankensteiniando uma outra idéia parecida com um corpus (Graças à Wikipédia, temos que: Corpus lingüístico é um corpo de textos escritos ou falados numa língua disponível para análise. O estudo de corpora (corpora é o plural de corpus) apresenta muitas vantagens. Em vez de consultar nossas intuições, ou de ‘extrair’ informações dos falantes, penosamente, uma a uma, podemos examinar um vasto material que foi produzido espontaneamente na fala ou na escrita das pessoas, e portanto podemos fazer observações precisas sobre o real comportamento lingüístico de gente real. Portanto os corpora podem nos proporcionar informações altamente confiáveis e isentas de opiniões e de julgamentos prévios, sobre os fatos de uma língua. O uso de corpus (plural corpora) está associado à Linguística de Corpus.) de um projeto sobre língua coreana. Resolvemos então construir, baseado em um projeto que acabou de ser feito por outro aluno do nosso laboratório (aquele que sumiu), um programa para a extração de palavras semelhantes baseada na relação entre as funções sintáticas e as palavras em vista. Com isso, construímos pares de palavras ligadas por meio de suas relações sintáticas de um corpus com cerca de 10.000.000 de palavras. Depois por meio desses pares, pusemo-nos a calcular o nível de similaridade entre essas palavras. O resultado final foi como o projeto anterior, relativamente baixo, isto é, as palavras encontradas não são tão similares quanto se esparava. Aí é que entra o "tcham" do nosso projeto, a língua coreana possui um alto grau de homófonos/homógrafos, por exemplo, bae, em coreano, pode significar "barco/navio", "barriga", "pêra" e "vezes (formador de numerais multiplicativos)". No primeiro experimento, todos esses significados se mostraram presentes em um só grupo, o que não traz bom resultado. Em suma, o programa dizia que barco é similar a pêssego que é similar a adição... o que não é verdade. Isso por causa da homofonografia (acabei de inventar) da palavra bae. Mudamos então o corpus para que nele constasse qual o significado das palavras homófonas e rodamos o program novamente. O resultado foi sensacional! Agora o programa diz que barco, automóvel, navio, cavalo, bicicleta, veículo, etc são equivalentes. Isso qualquer criança pode ver que é bem melhor que o resultado anterior. Todas as palavras acima têm em comum o fato de serem meios de transporte. O mesmo se passou com os sentidos de barriga e pêra. Exultamo-nos!
O interessante é que quando apresentamos essa idéia em sala de aula para o professor e os outros alunos do nosso curso, o professor se irritou com a gente e quase gritando disse: "Pra que fazer isso? Vocês não sabem que isso já foi feito? Vocês não sabem que o resultado não foi muito satisfatório em coreano? Vocês têm a pretensão de dizer que dá pra melhorar isso de alguma forma???" Continuando por uns 5 minutos e durante nossa apresentação com comentários "bem construtivos e apoiadores"... Depois disso, descobrimos que ele havia inscrito esse trabalho como trabalho em conjunto dele com o menino que sumiu (nessa época ele ainda não tinha sumido) para apresentar em uma conferência internacional sobre lingüística computacional. Aí deu pra entender a reação dele... Propusemo-nos a melhorar um trabalho que, sem que soubéssemos, ele iria apresentar na conferência. Mas e daí? Problema dele! Se ele se interessasse um pouco mais sobre a gente, isso não teria acontecido... Ele teria sabido disso antes e não teria ficado todo nervosinho na frente de todo mundo.
Bem, pra encurtar a história, acabou que entregamos o trabalho pra ele um pouco atrasados, tipo mais que uma semana de atraso. Muito disso por causa do tamanho dos corpora (plural de corpus) que demoravam por volta de 15 horas pra rodar e dar resultado. E quando víamos os resulatdos, tínhamos que modificar algumas variáveis pra ver se o resultado melhorava ou não... Isso tomou muito tempo... Eu sei que, no final das contas, depois de mais ou menos um mês de trabalho de cão, varando noite, dormindo no laboratório (quando dava tempo), voltando pra casa só pra tomar banho, e morrendo um dia inteiro na cama quando dava tempo, mandamos o trabalho pra ele por e-mail. Dois dias depois nos chamou em sua sala. Fomos meio com o rabo entre as pernas. Quando abrimos a porta, ele estava que era só sorrisos! Ele adorou nosso resultado, claro que nem passou pela sua cabeça de pedir desculpas o qqr coisa do gênero, mas resolveu aumentar nossa nota (que ele já tinha dado antes de ver o trabalho porque tínhamos demorado e ele tinha que entregar por causa do calendário). Fechamos o semestre com A+. Que beleza! Até que valeu todo o trabalho de doido que tivemos. E a satisfação de ver nosso projetinho dar seus frutos... e graças aos MEUS programas em Python! =) Senti-me super satisfeito!
Pois é, o Munhyon entrou com as idéias, eu entrei com a programação (que me ensinou pra caramba!!!), e ambos entramos com a redação do "paper" (não é papér de mineiro, tá? é pêiper de americano...). Foi um trabalho que se tivéssemos feito sozinhos, não teríamos passado de B, mas juntando nossas forças e idéias, acabamos tirando A+. Foi um senhor trabalho de equipe meu e do Munhyong, ficamos muito contentes, e nos aproximamos bastante. Antes éramos apenas colegas de laboratório, agora somos amigos. Finalmente! Depois de um ano... Brasileiro fala que japonês é difícil de fazer amizade... Vai tentar com coreano, vai! Êita!
Um abraço pro 6.
Inté.
Minha vida na Coréia: mestrado, viagens, enfim, meus pensamentos com muito café e kimchi. ^^
Itens compartilhados de Juliano
Mostrando postagens com marcador provas. Mostrar todas as postagens
Mostrando postagens com marcador provas. Mostrar todas as postagens
terça-feira, 8 de julho de 2008
segunda-feira, 9 de junho de 2008
Novo programa
Pois é. No último post eu estava aprendendo como programar em Python... Agora o negócio é pra valer. Este é o primeiro programa que estamos usando para ler um corpus de quase 200.000 frases e extrair as marcações sintáticas de cada palavra em relação à palavra à qual esta está subordinada. Tipo, no caso de "João viu o macaco", eu tenho que mostrar as informações como viu: sujeito(João), viu: objeto(macaco). Estamos focando em substantivos e verbos. Depois de fazer essa lista, vamos processar um outro corpus que, ao invés de marcações sintáticas, possui marcações semânticas, isto é, diz se "macaco" no caso acima se trata do animal ou da ferramenta usada para trocar pneus de automóveis... Com isso, vamos cruzar as duas informações e procurar por "campos semânticos", isto é, conjunto de palavras que possuem uma certa similaridade e são usadas em determinados contextos, criando um banco de dados que possa vir ser usado no futuro como base de um programa de tradução automática, por exemplo. Por enquanto, ainda está bem cru, mas não parece impossível que cheguemos lá. A propósito, resolvemos fazer juntos esse projeto, eu e o carinha que também trabalha lá no laboratório de lingüística computacional, o Kim Munhyeong. Ah, e outro detalhe, a pesquisa é com um corpus de língua coreana. o.O
Aí vai o leitor/processador do primeiro corpus:
Na verdade, o programa em si, são só as últimas linhas. Todas as classes presentes aqui, são de outro projeto chamado KLTK (Korean Language Toolkit), feito por um doutorando daqui. Esse KLTK está sendo feito nos moldes do NLTK (Natural Language Toolkit) para o processamento da língua coreana e do novo dicionário eletrônico que foi feito recentemente, o Grande Dicionário Eletrônico Sejong... Como diria o Thiago, tá mais pra o Milenar Grande Dicionário... hehe
Faltam 2 dias para apresentar o projeto e 8 dias para entregar o paper com tudo bonitinho. Parece que ainda falta um século...
Um abraço pra quem não está ocupado e pra quem está também. ;)
Fui...
Aí vai o leitor/processador do primeiro corpus:
#!/usr/bin/python
#encoding: utf-8
import sys, re, codecs
class ForestWalker:
def __init__(self, file):
self.file = file
def __iter__(self):
return self
def readtree(self):
# read sentence form line
line = self.readline()
tree = Tree(line.split(' ')[0])
# make list of nodes
list_of_nodes = []
line = self.readline()
while (line):
(ord, dep, tag1, tag2, wordform, morph_string) = line.split("\t")
morphs = self.parse_morph_string(morph_string)
word = Word(ord, wordform, morphs, morph_string)
list_of_nodes.append(Node(ord, dep, tag1, tag2, word))
line = self.readline()
# make tree with list of nodes
# set parent-child relations
for n in list_of_nodes:
if n.dep == n.ord:
tree.set_root(n)
else:
p = list_of_nodes[int(n.dep)-1]
n.parent = p
p.add_a_child(n)
tree.nodes = list_of_nodes
return tree
def parse_morph_string(self, morph_string):
morphs = []
m = morph_string
for m in morph_string.split('+'):
m = m.strip()
if m == "" :
pass
else :
if m == "/SW":
form, pos = "+", "SW"
elif m[0:2] == "//":
form, pos = "/", m[2:]
else :
try :
form, pos = m.split("/")
if pos == "" : pos = "_ERR_"
except :
form, pos = m, "_ERR_"
morphs.append(Morph(form,pos))
return morphs
def readline(self):
line = self.file.readline()
# EOF
if (line == '') : sys.exit(0)
return line.strip()
fields = line.strip().split("\t")
if len(fields) == 6 :
return fields
else :
return line.strip()
def next(self):
return self.readtree()
class TreeBank:
pass
class Tree:
def __init__(self, id):
self.id = id
self.nodes = []
self.root = None
self.terminals = []
def set_root(self, node):
self.root = node
def get_terminals(self):
if self.terminals :
pass
else:
for n in self.nodes:
if not n.children :
self.terminals.append(n)
return self.terminals
class Node:
def __init__(self, ord, dep, tag1, tag2, word):
self.parent = None
self.children = []
self.ord = ord
self.dep = dep
self.tag1 = tag1
self.tag2 = tag2
self.form = word.form
self.word = word
def add_a_child(self, node):
self.children.append(node)
class Morph:
def __init__(self, form, pos):
self.form = form
self.pos = pos
class Word:
def __init__(self, ord, form, morphs, morph_string):
self.ord = ord
self.form = form
self.morphs = morphs
self.morph_string = morph_string
def add_morph(self, morph):
self.morphs.append(morph)
def has_pos(self, pos):
for m in self.morphs:
if m.pos == pos :
return True
return False
def __str__(self):
str = ""
for m in self.morphs:
if str == "":
str = m.form
elif m.pos[0] == "S" :
str += m.form
else :
str += "-" + m.form
return str
#return reduce(lambda x,y: x.form+"-"+y.form, self.morphs)
class Encode:
def __init__(self, stdout, enc):
self.stdout = stdout
self.encoding = enc
def write(self, s):
self.stdout.write(s.encode(self.encoding))
def get_output_string1(morphs) :
str = ""
pos_arr = []
morphform_arr = []
for m in morphs:
pos_arr.append(m.pos)
morphform_arr.append(m.form)
str = ''.join(morphform_arr)
return str
def get_output_string2(morphs) :
str = ""
pos_arr = []
morphform_arr = []
for m in morphs:
pos_arr.append(m.pos)
morphform_arr.append(m.form)
str = ''.join(morphform_arr)
return str
def get_verbform(words):
v = re.compile(r".*?/")
w = ''.join(words)
arr = v.findall(w)
str = ''.join(arr)
return str
sys.stdout = Encode(sys.stdout, "utf8")
for s in ForestWalker(codecs.open(sys.argv[1], encoding="utf8")):
for n in s.nodes:
if re.compile(r'[ NV][PSQ]_[^C]').match(n.tag2):
if n.parent:
tg = re.compile('.*?_')
if re.compile(r'N.?').match(n.parent.tag2):
print "%s\t%s\t%sN" % (get_output_string1(n.word.morphs), tg.sub(r'', n.tag2), n.parent.word.morph_string.split(r'/')[0])
elif re.compile(r'V.?').match(n.parent.tag2):
print "%s\t%s\t%sV" % (get_output_string1(n.word.morphs), tg.sub(r'', n.tag2), get_verbform(n.parent.word.morph_string))
Na verdade, o programa em si, são só as últimas linhas. Todas as classes presentes aqui, são de outro projeto chamado KLTK (Korean Language Toolkit), feito por um doutorando daqui. Esse KLTK está sendo feito nos moldes do NLTK (Natural Language Toolkit) para o processamento da língua coreana e do novo dicionário eletrônico que foi feito recentemente, o Grande Dicionário Eletrônico Sejong... Como diria o Thiago, tá mais pra o Milenar Grande Dicionário... hehe
Faltam 2 dias para apresentar o projeto e 8 dias para entregar o paper com tudo bonitinho. Parece que ainda falta um século...
Um abraço pra quem não está ocupado e pra quem está também. ;)
Fui...
sábado, 17 de maio de 2008
Monty Python
Quando era criança e ouvi falar pela primeira vez de Monty Python, nem sabia direito o que era "cálice sagrado" ou quem eram mesmo eles... Sabia que era engraçado e acabava vendo os filmes sem muito entender. O negócio é que nunca imaginei que alguém em algum outro lugar do planeta também assistia e gostava tanto que resolveu botar o nome de Python numa linguagem de programação que ele resolveu inventar. Quando ele inventou ou quando eu assistia Monty Python sem muito entender, nunca imaginávamos que um dia *eu* estaria estudando essa língua e quebrando minha cabeça pra descobrir alguma coisa interessante que eu pudesse fazer com ela pra minha aula de lingüística computacional... Ai, ai, ai... A teoria do caos (ou efeito borboleta), mesclada às leis de Murphy são uma coisa danada de estranha. (E eu tô cansado, o verão está começando a aparecer. Vai ser um deus-nos-acuda o mês que vem, e ainda por cima, debaixo de 35 graus...)
Releituras 2½
Bem, como vocês já perceberam, o tempo foi bem escasso durante esta semana. Mal tive tempo de checar os e-mails, quanto mais pensar em escrever no blog ou mesmo no twitter!!!
O fim do semestre se aproxima e com ele todos os trabalhos, e outros tipos de avaliações... Para terça, tenho que escrever um "review" a respeito de dois artigos sobre lingüística histórica, preparar um relatório sobre a "grande mudança vocálica" (não sei se é esse o nome em português), que é quando as palavras do inglês passaram a ser pronunciadas de forma estranha: cake era "ka-ke" até um dia que eles resolveram falar "keik"; além disso, tenho que escrever um paper (um artigo científico, praticamente pronto para publicação) sobre alguma coisa de lingüística computacional até o dia 11 do mês que vem, e eu nem sei o que fazer. Sei lá... Como diz o Chico, "a gente vai levando, a gente vai levando, a gente vai levando"...
Quanto ao título do post, aproveitando que a últimas publicações foram a respeito de releituras musicais e etcs, olha isso que eu achei:
Abraço e fui.
O fim do semestre se aproxima e com ele todos os trabalhos, e outros tipos de avaliações... Para terça, tenho que escrever um "review" a respeito de dois artigos sobre lingüística histórica, preparar um relatório sobre a "grande mudança vocálica" (não sei se é esse o nome em português), que é quando as palavras do inglês passaram a ser pronunciadas de forma estranha: cake era "ka-ke" até um dia que eles resolveram falar "keik"; além disso, tenho que escrever um paper (um artigo científico, praticamente pronto para publicação) sobre alguma coisa de lingüística computacional até o dia 11 do mês que vem, e eu nem sei o que fazer. Sei lá... Como diz o Chico, "a gente vai levando, a gente vai levando, a gente vai levando"...
Quanto ao título do post, aproveitando que a últimas publicações foram a respeito de releituras musicais e etcs, olha isso que eu achei:
Abraço e fui.
Assinar:
Postagens (Atom)