/ / Map word ngrams para contagem em scala - scala, nlp, n-gram

Mapear a palavra ngrams para contagem em scala - scala, nlp, n-gram

Eu estou tentando criar um mapa que passe por todosos ngrams em um documento e conta quantas vezes eles aparecem. Ngrams são conjuntos de n palavras consecutivas em uma frase (então, na última sentença, (Ngrams, são) é um grama de 2 gramas, são os próximos 2 gramas, e assim por diante). Eu já tenho código que cria um documento de um arquivo e o analisa em sentenças. Eu também tenho uma função para contar os ngrams em uma sentença, ngramsInSentence, que retorna Seq [Ngram].

Eu estou ficando preso sintaticamente sobre como criarmeu mapa conta. Estou interagindo com todos os ngrams do documento no loop for, mas não sei como mapear os ngrams para a contagem de quantas vezes eles ocorrem. Sou relativamente novo em Scala e a sintaxe está me evitando, embora eu "Estou claro conceitualmente sobre o que eu preciso!

def getNGramCounts(document: Document, n: Int): Counts = {
for (sentence <- document.sentences; ngram <- nGramsInSentence(sentence,n))
//I need code here to map ngram -> count how many times ngram appears in document
}

O tipo Counts acima, assim como Ngram, são definidos como:

type Counts = Map[NGram, Double]
type NGram = Seq[String]

Alguém sabe a sintaxe para mapear os ngrams do loop for para uma contagem de quantas vezes eles ocorrem? Por favor, deixe-me saber se você gostaria de mais detalhes sobre o problema.

Respostas:

2 para resposta № 1

Se eu estou interpretando corretamente o seu código, esta é uma tarefa bastante comum.

def getNGramCounts(document: Document, n: Int): Counts = {
val allNGrams: Seq[NGram] = for {
sentence <- document.sentences
ngram <- nGramsInSentence(sentence, n)
} yield ngram

allNgrams.groupBy(identity).mapValues(_.size.toDouble)
}

o allNGrams variável coleta uma lista de todos os NGrams que aparecem no documento.
Você deve eventualmente virar para Streams se o documento é grande e você não pode manter toda a seqüência na memória.

Os seguintes groupBycria um Map[NGram, List[NGram]] que agrupa seus valores por sua identidade (o argumento para o método define os critérios para "identificação agregada") e agrupa os valores correspondentes em uma lista.

Você só precisa mapear os valores (o List[NGram]) para o seu size para obter quantos valores recorrentes havia de cada NGram.


Eu tomei como certo que:

  1. NGram tem a implementação correta esperada de equals + hashcode
  2. document.sentences retorna um Seq[...]. Se não, você deve esperar allNGrams para ser do tipo de coleta correspondente.

ATUALIZADA com base nos comentários

Eu erradamente assumi que o groupBy(_) iria atalho o valor de entrada. Use o identity função em vez disso.

Converti a contagem para um Double


0 para resposta № 2

Aprecie a ajuda - Eu tenho o código correto agora usando as sugestões acima. O seguinte retorna o resultado desejado:

def getNGramCounts(document: Document, n: Int): Counts = {
val allNGrams: Seq[NGram] = (for(sentence <- document.sentences;
ngram <- ngramsInSentence(sentence,n))
yield ngram)
allNGrams.groupBy(l => l).map(t => (t._1, t._2.length.toDouble))
}