2009-05-09 12 views
1

Ich möchte einen Algorithmus, der alle möglichen Phrasen in einem Textblock erstellen würde. Zum Beispiel im Text:Algorithmus zur Analyse von Text von Wörtern

"My username is click upvote. I have 4k rep on stackoverflow" 

Es würde die folgenden Kombinationen erstellen:

"My username" 
"My Username is" 
"username is click" 
"is click" 
"is click upvote" 
"click upvote" 
"i have" 
"i have 4k" 
"have 4k" 
.. 

Sie bekommen die Idee. Grundsätzlich geht es darum, alle möglichen Kombinationen von "Phrasen" aus einem Satz herauszuholen. Irgendwelche Gedanken, wie Sie das am besten umsetzen können?

+0

Aber was sind die Regeln, die diese Phrasen gebaut werden? – Gumbo

+0

Wie es aussieht, sind es 2-3 aufeinander folgende Wörter ... – Tomalak

+11

Natürliche Sprachverarbeitung == Welt des Schmerzes – Greg

Antwort

5

Grundsätzlich müssen Sie zuerst den Block des Textes in Sätze trennen. Das ist knifflig genug, sogar auf Englisch, da Sie nach Punkten, Fragezeichen, Ausrufezeichen und anderen Satzabschlüssen Ausschau halten müssen.

Dann verarbeiten Sie jeweils einen Satz nach dem Entfernen aller Interpunktionszeichen (Kommas, Semikolons, Doppelpunkte usw.).

Dann, wenn Sie mit einer Reihe von Worten sind links, wird es einfacher:

for i = 1 to num_words-1: 
    for j = i+1 to num_words: 
     phrase = words[i through j inclusive] 
     store phrase 

Das ist es, ziemlich einfach (nach anfänglichen Massieren des Textblockes, der nicht so einfach sein wie Sie denken).

Dies gibt Ihnen alle Sätze von zwei oder mehr Wörtern in jedem Satz.

Die Trennung in Sätze, die Trennung in Wörter, das Entfernen von Satzzeichen usw. wird das härteste Teil sein, aber ich habe Ihnen bereits einige einfache Anfangsregeln gezeigt. Der Rest sollte jedes Mal hinzugefügt werden, wenn ein Textblock den Algorithmus durchbricht.

Update:

Wie gewünscht, hier einige Java-Code, der die Sätze gibt:

public class testme { 
    public final static String text = 
     "My username is click upvote." + 
     " I have 4k rep on stackoverflow."; 

 

public static void procSentence (String sent) { 
     System.out.println ("=========="); 
     System.out.println ("sentence [" + sent + "]"); 

     // Split sentence at whitspace into array. 

     String [] sa = sent.split("\\s+"); 

     // Process each starting word. 

     for (int i = 0; i < sa.length - 1; i++) { 

      // Process each phrase. 

      for (int j = i+1; j < sa.length; j++) { 

       // Build the phrase. 

       String phrase = sa[i]; 
       for (int k = i+1; k <= j; k++) { 
        phrase = phrase + " " + sa[k]; 
       } 

       // This is where you have your phrase. I just 
       // print it out but you can do whatever you 
       // wish with it. 
       System.out.println (" " + phrase); 
      } 
     } 
    } 

 

public static void main(String[] args) { 
     // This is the block of text to process. 

     String block = text; 
     System.out.println ("block [" + block + "]"); 

     // Keep going until no more sentences. 

     while (!block.equals("")) { 
      // Remove leading spaces. 

      if (block.startsWith(" ")) { 
       block = block.substring(1); 
       continue; 
      } 

      // Find end of sentence. 

      int pos = block.indexOf('.'); 

      // Extract sentence and remove it from text block. 

      String sentence = block.substring(0,pos); 
      block = block.substring(pos+1); 

      // Process the sentence (this is the "meat"). 

      procSentence (sentence); 

      System.out.println ("block [" + block + "]"); 
     } 
     System.out.println ("=========="); 
    } 
} 

die Ausgänge:

block [My username is click upvote. I have 4k rep on stackoverflow.] 
========== 
sentence [My username is click upvote] 
    My username 
    My username is 
    My username is click 
    My username is click upvote 
    username is 
    username is click 
    username is click upvote 
    is click 
    is click upvote 
    click upvote 
block [ I have 4k rep on stackoverflow.] 
========== 
sentence [I have 4k rep on stackoverflow] 
    I have 
    I have 4k 
    I have 4k rep 
    I have 4k rep on 
    I have 4k rep on stackoverflow 
    have 4k 
    have 4k rep 
    have 4k rep on 
    have 4k rep on stackoverflow 
    4k rep 
    4k rep on 
    4k rep on stackoverflow 
    rep on 
    rep on stackoverflow 
    on stackoverflow 
block [] 
========== 

Nun, bedenken Sie dies ziemlich einfach ist Java (einige könnte es C in einem Java-Dialekt geschrieben sagen :-). Es soll nur veranschaulichen, wie Wortgruppen aus einem Satz ausgegeben werden, wenn Sie danach gefragt haben.

Es tut nicht tun alle die ausgefallene Satzerkennung und Satzentfernung, die ich in der ursprünglichen Antwort erwähnte.

+0

Können Sie ein PHP/C/Java-ähnliches Beispiel für Ihre For-Schleife geben? Ich habe Schwierigkeiten zu verstehen, was es tut, weil ich mit der Syntax nicht vertraut bin. Wenn Sie den Code in Java zeigen könnten, wäre das großartig –

5

Nun, ich weiß nicht PHP oder Java, aber im Grunde wollen Sie eine doppelte Schleife über alle Wörter in Ihrem Text. Hier einige Pseudo-Code:

words = split(text) 
n = len(words) 
for i in 1...n-1 {  // i = first word in phrase 
    for j in i+1...n {  // j = last word in phrase 
     phrase = join(words[i:j]) 
     print phrase 
    } 
} 

Beachten Sie, dass die zweite Schleife von i beginnt, nicht 1. Dies gibt Ihnen alle Phrasen, die aus Wortnummer beginnen i Nummer j zu Wort, die größer ist als i (so alle Sätze habe mindestens zwei Wörter).

Ah, ich habe gerade festgestellt, dass Sie wahrscheinlich keine Satzgrenzen überschreiten wollen. Sie wollen also eine äußere Schleife, die den Text zuerst in Sätze aufteilt, dann aber in jedem Satz.

Dies scheint ziemlich klar, wenn Sie irgendwelche Programmierkenntnisse überhaupt haben, aber nur für den Fall: Die for Aussagen sind Schleifen [wie for(i=1; i<=n; i++)], split ist eine Funktion, die einen String und teilt sie in eine Reihe von Worten - Das ist nicht ganz trivial, aber es gibt wahrscheinlich eine Bibliotheksfunktion, len gibt die Länge des Arrays, join setzt sie wieder zusammen mit Leerzeichen dazwischen, und die Syntax [i:j] bedeutet alle Elemente von i bis j inklusive (in Python, das wäre eigentlich [i:j+1]). Oh, und ich habe implizit angenommen, dass Arrays bei Index 1 und nicht bei Null beginnen; Ich lasse auf 0-basierte C Arrays als eine Übung zu ändern ...

schließlich die spezifischen Fragen zu beantworten:

  • Beachten Sie, dass die „zweite“ Schleife ist eigentlich eine innere Schleife; Für jeden Wert von i (das erste Wort der Phrase) wir Schleife von i+1 bis zum Ende des Satzes, um das letzte Wort der Phrase zu geben.

  • Nun, da wir die Anzahl der ersten und letzten Worte haben, die join Funktion - die Sie schreiben müssen - verkettet die einzelnen Strings word[i], word[i+1], ... word[j] mit Leerzeichen zwischen den Satz zu bilden. In der Praxis kann dies bedeuten, dass die Funktion wie join(words, i, j) deklariert werden kann und die Zeichenfolge zurückgibt, obwohl einige Sprachen Möglichkeiten haben, dies zu vereinfachen.

+0

Können Sie den Code in Java übersetzen? –

+4

Wenn Sie seinen ersten Satz lesen, sehen Sie, dass er PHP oder Java nicht kennt. Zusätzlich sollte der gegebene Pseudocode einfach genug sein, um in Java selbst zu übersetzen, vorausgesetzt einige grundlegende Java-Kenntnisse und ein wenig Suchen. –

+0

Es wäre, wenn ich den Pseudocode verstehen könnte, macht es wenig Sinn für mich. Er hat Java als eines seiner Tags. –

2

Token Sie einfach den Satz und verwenden Sie den CombiationGenerator. Der Algorithmus wird von Kenneth H. Rosen, Discrete Mathematics and Its Applications, 2. Auflage (NY: McGraw-Hill, 1991), S. 284-286, beschrieben.

Hier ist der Code und Anwendungsbeispiel: http://www.merriampark.com/comb.htm

+0

Wieder (wie in Jess 'Versuch) wollen wir nicht alle möglichen Kombinationen - nur aufeinander folgende Einträge. Dies ist ein viel einfacheres Problem (über mehrere Male gelöst)! –

+0

Ahhh ... jetzt sehe ich. – Cuga

1

konnte mit str_word_count(); spielen und bauen es, wie Sie möchten.

1

Sie wissen vielleicht schon, dass der Fachbegriff für solche Phrasen Shingle ist. Sie können Schindeln für Eingabetext mit Lucene ShingeMatrixFilter bekommen.

+0

Nur eine Anmerkung, ShingleMatrixFilter ist bereits veraltet und wird in 4.0 entfernt. Vielleicht möchten Sie stattdessen ShingleFilter verwenden. –

Verwandte Themen