En introduktion til Bag of Words, og hvordan man kode den i Python til NLP

Hvide og sorte ridsefliser på sort overflade af Pixabay

Bag of Words (BOW) er en metode til at udtrække funktioner fra tekstdokumenter. Disse funktioner kan bruges til træning af maskinlæringsalgoritmer. Det skaber et ordforråd for alle de unikke ord, der forekommer i alle dokumenter i træningssættet.

Kort sagt er det en samling af ord, der repræsenterer en sætning med ordtælling og for det meste ser man bort fra den rækkefølge, de vises i.

BOW er en metode, der er almindeligt anvendt med:

  1. Naturlig sprogbehandling
  2. Indhentning af oplysninger fra dokumenter
  3. Dokumentklassifikationer

På et højt niveau involverer det følgende trin.

Genererede vektorer kan indlæses til din maskinlæringsalgoritme.

Lad os starte med et eksempel til at forstå ved at tage nogle sætninger og generere vektorer til dem.

Overvej nedenstående to sætninger.

1. "John kan godt lide at se film. Mary kan også lide film."
2. "John kan også lide at se fodboldkampe."

Disse to sætninger kan også repræsenteres med en samling af ord.

1. ['John', 'likes', 'to', 'watch', 'film.', 'Mary', 'likes', 'film', 'too.']
2. ['John', 'også', 'likes', 'to', 'watch', 'football', 'games']

Fjern desuden flere forekomster af ordet for hver sætning og brug ordtællingen til at repræsentere dette.

1. {"John": 1, "likes": 2, "to": 1, "watch": 1, "film": 2, "Mary": 1, "too": 1}
2. {"John": 1, "også": 1, "likes": 1, "til": 1, "watch": 1, "football": 1, "games": 1}

Forudsat at disse sætninger er en del af et dokument, er nedenunder den kombinerede ordfrekvens for hele vores dokument. Begge sætninger tages i betragtning.

 {"John": 2, "likes": 3, "to": 2, "watch": 2, "film": 2, "Mary": 1, "too": 1, "also": 1, " fodbold ": 1," spil ": 1}

Ovenstående ordforråd fra alle ordene i et dokument med deres respektive ordtælling vil blive brugt til at oprette vektorer til hver af sætningerne.

Længden af ​​vektoren vil altid være lig med ordforrådets størrelse. I dette tilfælde er vektorlængden 11.

For at repræsentere vores originale sætninger i en vektor initialiseres hver vektor med alle nuller - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Dette efterfølges af iteration og sammenligning med hvert ord i vores ordforråd og forøgelse af vektorværdien, hvis sætningen har det ord.

John kan godt lide at se film. Mary kan også godt lide film.
[1, 2, 1, 1, 2, 1, 1, 0, 0, 0]
John kan også lide at se fodboldkampe.
[1, 1, 1, 1, 0, 0, 0, 1, 1, 1]

For eksempel, i sætning 1 vises ordet lide i anden position og vises to gange. Så det andet element i vores vektor til sætning 1 vil være 2: [1, 2, 1, 1, 2, 1, 1, 0, 0, 0]

Vektoren er altid proportional med størrelsen på vores ordforråd.

Et stort dokument, hvor det genererede ordforråd er enormt, kan resultere i en vektor med masser af 0 værdier. Dette kaldes en sparsom vektor. Sparsomme vektorer kræver mere hukommelse og beregningsressourcer ved modellering. Det store antal positioner eller dimensioner kan gøre modelleringsprocessen meget udfordrende for traditionelle algoritmer.

Kodning af vores BOW-algoritme

Input til vores kode vil være flere sætninger, og output vil være vektorerne.

Inputarrayet er dette:

["Joe ventede på toget", "Toget var sent", "Mary og Samantha tog bussen",
"Jeg kiggede efter Mary og Samantha på busstationen",
"Mary og Samantha ankom tidligt på busstationen, men ventede til middag på bussen"]

Trin 1: Tone en sætning

Vi starter med at fjerne stopwords fra sætningerne.

Stopwords er ord, der ikke har tilstrækkelig betydning til at blive brugt uden vores algoritme. Vi ønsker ikke, at disse ord optager plads i vores database eller optager værdifuld behandlingstid. Til dette kan vi let fjerne dem ved at gemme en liste over ord, som du betragter som stopord.

Tokenisering er handlingen om at opdele en række strenge i stykker som ord, nøgleord, sætninger, symboler og andre elementer kaldet tokens. Tokens kan være individuelle ord, sætninger eller endda hele sætninger. I processen med tokenisering kasseres nogle tegn som tegnsætningstegn.

def word_extraction (sætning):
    ignorere = ['a', "the", "is"]
    ord = re.sub ("[^ \ w]", "", sætning) .split ()
    cleaning_text = [w.lower () for w med ord, hvis w ikke i ignorere]
    returnere cleaning_text

For mere robust implementering af stopwords kan du bruge python nltk-bibliotek. Det har et sæt foruddefinerede ord pr. Sprog. Her er et eksempel:

import nltk
fra nltk.corpus import stopwords
 sæt (stopwords.words (engelsk))

Trin 2: Anvend tokenisering på alle sætninger

def tokenize (sætninger):
    ord = []
    for sætning i sætninger:
        w = word_extraction (sætning)
        words.extend (w)
        
    ord = sorteret (liste (sæt (ord)))
    returnere ord

Metoden itererer alle sætninger og tilføjer det udpakkede ord til en matrix.

Outputen fra denne metode vil være:

['og', 'ankom', 'ved', 'bus', 'men', 'tidligt', 'for', 'jeg', 'joe', 'sent', 'kigget', 'mary', ' middag ',' samantha ',' station ',' the ',' tog ',' tog ',' indtil ',' ventede ',' var ']

Trin 3: Lav ordforråd og generer vektorer

Brug metoderne defineret i trin 1 og 2 til at oprette dokumentordforråd og udtrække ordene fra sætningerne.

def generere_bue (allsentences):
    vocab = tokenize (allsentences)
    print ("Ordliste til dokument \ n {0} \ n" .format (vokab));
til sætning i allsentences:
        ord = ord_ekstraktion (sætning)
        bag_vector = numpy.zeros (len (vokab))
        for w i ord:
            for i, ord i enumerate (vokab):
                hvis ord == w:
                    bag_vector [i] + = 1
                    
        print ( "{0} \ n {1} \ n" .format (punktum, numpy.array (bag_vector)))

Her er den definerede input og udførelse af vores kode:

allsentences = ["Joe ventede på togtoget", "Toget var sent", "Mary og Samantha tog bussen",
"Jeg kiggede efter Mary og Samantha på busstationen",
"Mary og Samantha ankom tidligt på busstationen, men ventede til middag på bussen"]
generate_bow (allsentences)

Udgangsvektorerne for hver af sætningerne er:

Produktion:
Joe ventede på togtoget
[0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 2. 0. 1. 0.]
Toget var sent
[0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 1.]
Mary og Samantha tog bussen
[1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0.]
Jeg kiggede efter Mary og Samantha på busstationen
[1. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0.]
Mary og Samantha ankom tidligt på busstationen, men ventede indtil middag på bussen
[1. 1. 1. 2. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1. 0. 0. 0. 1. 1. 0.]

Som du kan se, blev hver sætning sammenlignet med vores ordliste genereret i trin 1. Baseret på sammenligningen kan vektorelementværdien øges. Disse vektorer kan bruges i ML-algoritmer til dokumentklassificering og forudsigelser.

Vi skrev vores kode og genererede vektorer, men lad os nu forstå en pose med ord lidt mere.

Indblik i en pose med ord

BOW-modellen overvejer kun, om et kendt ord forekommer i et dokument eller ej. Det er ligeglad med mening, kontekst og rækkefølge, de vises i.

Dette giver den indsigt, at lignende dokumenter vil have ordtællinger, der ligner hinanden. Med andre ord, jo mere ens ordene i to dokumenter er, desto mere ens kan dokumenterne være.

Begrænsninger af BOW

  1. Semantisk betydning: den grundlæggende BOW-tilgang tager ikke hensyn til betydningen af ​​ordet i dokumentet. Det ignorerer fuldstændigt den kontekst, som det er brugt i. Det samme ord kan bruges flere steder baseret på konteksten eller ord i nærheden.
  2. Vektorstørrelse: For et stort dokument kan vektorstørrelsen være enorm, hvilket resulterer i meget beregning og tid. Det kan være nødvendigt at ignorere ord baseret på relevans for din brugssag.

Dette var en lille introduktion til BOW-metoden. Koden viste, hvordan den fungerer på et lavt niveau. Der er meget mere at forstå om BOW. I stedet for at opdele vores sætning i et enkelt ord (1-gram), kan du for eksempel opdele i parret med to ord (bi-gram eller 2-gram). Til tider synes bi-gram-repræsentation at være meget bedre end at bruge 1-gram. Disse kan ofte repræsenteres ved anvendelse af N-gram notation. Jeg har anført nogle forskningsartikler i ressourceafsnittet for mere dybtgående viden.

Du behøver ikke at kode BOW, når du har brug for det. Det er allerede en del af mange tilgængelige rammer som CountVectorizer i sci-kit learning.

Vores tidligere kode kan erstattes med:

fra sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer ()
X = vectorizer.fit_transform (allsentences)

print (X.toarray ())

Det er altid godt at forstå, hvordan bibliotekerne i rammer fungerer, og forstå metoderne bag dem. Jo bedre du forstår begreberne, jo bedre kan du bruge rammer.

Tak, fordi du læser artiklen. Den viste kode er tilgængelig på min GitHub.

Du kan følge mig på Medium, Twitter og LinkedIn. For spørgsmål kan du kontakte mig på e-mail (praveend806 [at] gmail [dot] com).

Ressourcer til at læse mere på en pose med ord

  1. Wikipedia-BOW
  2. Forstå Bag-of-Words-model: En statistisk ramme
  3. Semantik-bevare taske-af-ord-modeller og applikationer