Frequência de palavras em textos de idioma diferente do inglês: como mesclar formas singular e plural etc.?

4

Estou classificando as palavras do idioma francês em alguns arquivos de texto de acordo com frequência com foco em insight em vez de significância estatística. O desafio é preservar caracteres acentuados e lidar com os formulários de artigos na frente das vogais ( l' , d' ) no contexto da formatação de tokens de palavras para classificação.

O tópico das palavras mais frequentes em um arquivo tem várias formas (1 | 2 | < href="https://unix.stackexchange.com/q/88978/44370"> 3 | 4 ). Então eu coloquei esta função usando utilitários GNU :

compt1 () {
for i in *.txt; do
    echo "File: $i"
    sed -e 's/ /\
/g' <"$i" | sed -e 's/^[[:alpha:]][[:punct:]]\(.*\)//' | sed -e 's/\(.*\)/\L/' | grep -hEo "[[:alnum:]_'-]+" | grep -Fvwf /path_to_stop_words_file | sort | uniq -c | sort -rn 
done
}

... que comercializa espaços para novas linhas; apara um caractere seguido de pontuação que está no início da linha; então converte tudo para minúsculas; usa este compacto grep construct que combina caracteres constituintes de palavras para criar tokens; em seguida, remove as palavras de parada e, finalmente, há a classificação usual. O arquivo de parada contém um segmento com caracteres individuais, portanto você deve ter cuidado com a forma como é usado, mas o A análise fornecida sobre como criar hastes para palavras em diferentes idiomas é realmente interessante!

Agora, quando comparo a frequência de uma palavra significativa com a saída de grep -c diretamente nos arquivos, acho que está perto o suficiente dentro de uma margem de erro.

Perguntas :

  • Como eu poderia modificar isso para mesclar a freqüência de plurais com seus formas singulares, ou seja, palavras que compartilham um prefixo comum com uma variável 1 sufixo de caractere?
  • Estou tentando avaliar se a parte grep em particular funcionaria com o que está em OSX ?

1. Não posso fornecer dados de origem, mas posso fornecer este arquivo como exemplo. As palavras heure e enfant no texto fornecem um exemplo. O primeiro aparece duas vezes no texto, incluindo uma vez como "l'heure", e ajuda a validar se o comando funciona ou não. Este último aparece tanto no singular quanto no plural ( enfant / enfants ) e se beneficiaria com a fusão aqui.

    
por jus cogens prime 19.07.2014 / 15:59

3 respostas

8

Você realmente não conseguirá fazer isso com um script sed simplista. Eu estou supondo que você vai querer reduzir para "formas de citação", colapsando todas as inflexões em um formulário base.

Isso significa que adjetivos como protegido, protegido, protegido, protegido contam como a mesma coisa, o adjetivo base / particípio protegido . Da mesma forma, todas as inflexões do verbo protéger - como protège, protégeons, protégeais, protégeasse, protégeâmes, protégeront, protégeraient , etc. - seriam reduzidas a esse verbo base. / p>

Isso significa que você precisa saber coisas sobre a morfologia flexional da linguagem. Pior ainda, você precisará entender algo sobre a sintaxe real da linguagem, incluindo as inflexões e distinguir homógrafos.

Eu fiz muito abordagens simples para pelo menos a primeira parte deste usando Perl. É realmente uma dor na bunda. Aqui está uma amostra de código que usei para gerar chaves de classificação para cidades e vilas na península ibérica:

       # 1st strip leading articles
          s/^L'//;    # Catalan
          s{ ^
            (?:
        # Castilian
                El
              | Los
              | La
              | Las

        # Catalan 
              | Els
              | Les         
              | Sa
              | Es

        # Gallego
              | O       
              | Os
              | A
              | As      
            ) 
            \s+ 
          }{}x;
        # 2nd strip interior particles
          s/\b[dl]'//g;   # Catalan
          s{ 
            \b
            (?:
                el  | los | la | las | de  | del | y          # ES
              | els | les | i  | sa | es | dels               # CA 
              | o   | os  | a  | as  | do  | da | dos | das   # GAL
            )
            \b
        }{}gx;

Isso retira os artigos e as partículas para que eles não sejam contabilizados para fins de classificação. Mas você terá que lidar com formulários como l'autre com o chamado "curly-quote", que é realmente U + 2019 RIGHT SINGLE QUOTATION MARK, a forma preferida para o apóstrofo. Eu normalizei aqueles em linha reta com um s/’/'/g primeiro.

Ah, e você terá que lidar com codificações: MacRoman não é o mesmo que UTF-8 ou ISO-8859-1 - não por um longo caminho.

Honestamente, você provavelmente quer usar algo como o algoritmo de "bola de neve", especificando francês como a linguagem. Certamente, o módulo Lingua::Stem::Snowball de Perl sabe como fazer isso. Você pode pesquisar por módulos Perl relacionados à lingüística francesa usando esta consulta .

Mas o problema só vai levar você até certo ponto. Você não fará um bom trabalho até aplicar a análise morfossintática - o que significa que você precisa gerar uma análise das frases e atribuir partes da fala a cada elemento.

Isso requer muito mais trabalho. A boa notícia é que existem ferramentas dedicadas para isso, algumas das quais de fato funcionam em francês. Mas isso realmente está afetando muito, porque agora você se aventurou nos campos de Processamento de Linguagem Natural e Lingüística Computacional. Não há um grande lar para essas questões aqui, mas elas provavelmente seriam melhor respondidas em Linguistics.SE; Eu não sei.

    
por 19.07.2014 / 16:53
3

O processamento de linguagem natural é complexo. Fazer isso com expressões regulares é como analisar o HTML com expressões regulares , apenas pior. Leia excelente resposta do tchrist para algumas dicas de como usar a abordagem do seu problema. Vou responder brevemente a parte sobre a portabilidade do seu uso de ferramentas de processamento de texto unix.

O denominador comum a todos os sistemas modernos semelhantes a unix é a especificação POSIX . O recurso mais útil é o Open Group Specification Issue 6 também conhecido como Single Unix Specification versão 3 (OGS Edição 7 = SUS versão 4 não está totalmente implementado em muitos sistemas), o que inclui e estende o POSIX e, utilmente, está disponível online e para download (por exemplo, em Debian ). Se você está interessado apenas em portabilidade para Linux não embarcado (e Cygwin) e para OSX, verifique os manuais GNU e o man pages do OSX .

Você está usando várias opções não-POSIX para grep , mas todas estão disponíveis tanto no GNU quanto no OSX (o OSX usa o grep do FreeBSD, que procura emular a maioria das construções GNU). Se você quiser POSIX, precisará evitar algumas opções:

  • grep -h para suprimir o nome do arquivo: chame grep em um arquivo por vez ou passe os arquivos para cat primeiro.
  • grep -o para gerar apenas a parte correspondente: use sed ou awk .
  • grep -w para corresponder apenas a palavras inteiras: pesquise um padrão como (^|[^[:alnum:]])needle($|[^[:alnum:]]) .

Você está usando uma construção somente GNU no sed: a diretiva \L para diminuir uma substituição no comando s . Não há nada como isso em outras implementações de sed. Em geral, você pode usar o awk: divida a entrada para isolar a string a ser substituída e chame tolower . Para diminuir a entrada inteira, chame tr '[:upper:]' '[:lower:]' .

    
por 20.07.2014 / 04:40
1

A resposta selecionada realmente fornece uma ótima introdução aos desafios no campo de Processamento de Linguagem Natural e Lingüística Computacional e lá é certamente mais informações sobre ativos SE dedicados . Eu queria fornecer um complemento que enfatizasse esses desafios e me proporcionasse uma "correção" temporária.

Acho que, em alguns casos, 1 pode cortar o último s com sed para obter um resultado bastante seguro, mas interessante:

s/\(.*[bcdefghjklmnpqrtvwxyzéëêàâûùôö]\)s$//

Isto compacta algumas 50 linhas na amostra fornecida quando usada com a função original.

Então, eu tentei sed com o seguinte, que é incompleto e não funciona como pretendido - mas apresenta dificuldades e é útil na minha opinião para entender o que resposta explicou:

sed '

h;
s/^\(par\|col\|tap.*\)//
t RVv

h;
s/^\(par\|col\|tap.*\)//
t RVc

h;
s/^\([aeiouyâàëéêèïîôûù][aeiouyâàëéêèïîôûù]..*\)$//
t RVnotpctv_v

h;
s/^\(.*.[aeiouyâàëéêèïîôûù]....*\)//
t RVnotpctother
b

:RVv
s/^\(par\|col\|tap[bcdfghjklmnpqrstvwxz][aeiouyâàëéêèïîôûù].*\)//
t R1

:RVc
s/^\(par\|col\|tap[aeiouyâàëéêèïîôûù][bcdfghjklmnpqrstvwxz].*\)//
t R1

:RVnotpctv_v
s/^\([aeiouyâàëéêèïîôûù][aeiouyâàëéêèïîôûù].[aeiouyâàëéêèïîôûù][bcdfghjklmnpqrstvwxz].*\)$//
t R1

:RVnotpctother
s/^\(.*[aeiouyâàëéêèïîôûù][bcdfghjklmnpqrstvwxz].*\)//
t R1

:R1        
s/ement$\|ements$\|ité$\|ités$\|if$\|ive$\|ifs$\|ives$\|euse$\|euses$//
s/é$\|ée$\|ées$\|és$\|èrent$\|er$\|era$\|erai$\|eraIent$\|erais$\|erait$\|eras$\|erez$\|eriez$\|erions$\|erons$\|eront$\|ez$\|iez$\|ions$\|eons$//
s/eâmes$\|eât$\|eâtes$\|ea$\|eai$\|eaIent$\|eais$\|eait$\|eant$\|eante$\|eantes$\|eants$\|eas$\|easse$\|eassent$\|easses$\|eassiez$\|eassions$//
s/âmes$\|ât$\|âtes$\|a$\|ai$\|aIent$\|ais$\|ait$\|ant$\|ante$\|antes$\|ants$\|as$\|asse$\|assent$\|asses$\|assiez$\|assions$//
s/[bcdfghjklmnpqrstvwxz]îmes$\|ît$\|îtes$\|i$\|ie$\|ies$\|ir$\|ira$\|irai$\|iraIent$\|irais$\|irait$\|iras$\|irent$\|irez$\|iriez$\|irions$\|irons$\|iront$\|is$\|issaIent$\|issais$\|issait$\|issant$\|issante$\|issantes$\|issants$\|isse$\|issent$\|isses$\|issez$\|issiez$\|issions$\|issons$\|it$//
s/Y/i/
s/ç/c/
t R2

:R2
s/ance$\|iqUe$\|isme$\|able$\|iste$\|eux$\|ances$\|iqUes$\|ismes$\|ables$\|istes$//
s/atrice$\|ateur$\|ation$\|atrices$\|ateurs$\|ations$//
s/logie$\|logies$/log/
s/usion$\|ution$\|usions$\|utions$/u/
t Res

:Res
##Residual
s/ier$\|ière$\|Ier$\|Ière$/i/
s/\(.*[bcdefghjklmnpqrtvwxyzéëêàâûùôö]\)s$//
##Undouble
s/\(en\)n$//
s/\(on\)n$//
s/\(et\)t$//
s/\(el\)l$//
s/\(eil\)l$//
##Unaccent
s/\(.*\)\(é\)\([bcdefghjklmnpqrtvwxyzéëêàâûùôö]*\)$/e/
s/\(.*\)\(è\)\([bcdefghjklmnpqrtvwxyzéëêàâûùôö]*\)$/e/
s/\(.*\)e$//
t
'

Em alguns casos, ele consegue remover a palavra para algum radical, mas há uma escolha muito consciente de evitar lidar com palavras que contenham apenas alguns caracteres, pois ele implementa apenas alguns recursos pequenos (e não < em> R2 por exemplo), e mal nisso. Mas compara outras 50-60 linhas na amostra, já que inclui a expressão anterior sed . 2 Para mais informações eu vou olhar para Linguística !

1. Isso tudo é baseado no meu "entendimento" do pseudo-código / descrição do bola de neve algoritmo francês.

2. É errado em muitos casos, mas executá-lo interativamente na linha me forneceu a visão que eu estava procurando quando se olha para palavras como parlons et bombons . Eu percebi que não há nada intrínseco nessas duas palavras que dita por que o primeiro (verbo) tem que ser stipped de seu ons enquanto o outro (um substantivo) somente de seu s . É sobre analisar as partes da fala como foi explicado ...

    
por 21.07.2014 / 14:16