Bevezetés a Bag of Words-ba és annak kódolásának Python-ba az NLP-hez

A szavak táskája (BOW) egy módszer a szöveges dokumentumok funkcióinak kinyerésére. Ezek a funkciók felhasználhatók gépi tanulási algoritmusok képzésére. Szótárat készít az összes egyedi szóról, amely a képzési készlet összes dokumentumában előfordul.

Egyszerűbben fogalmazva, ez egy olyan szógyűjtemény, amely egy mondatot képvisel szószámmal, és többnyire figyelmen kívül hagyja a megjelenés sorrendjét.

A BOW egy olyan megközelítés, amelyet széles körben alkalmaznak:

  1. Természetes nyelv feldolgozása
  2. Információkeresés dokumentumokból
  3. Dokumentumok osztályozása

Magas szinten a következő lépéseket foglalja magában.

A generált vektorok bevihetők a gépi tanulási algoritmusba.

Kezdjük egy megértési példával, megfogalmazva néhány mondatot és vektorokat generálva azok számára.

Tekintsük az alábbi két mondatot.

1. "John likes to watch movies. Mary likes movies too."
2. "John also likes to watch football games."

Ez a két mondat szógyűjteménnyel is ábrázolható.

1. ['John', 'likes', 'to', 'watch', 'movies.', 'Mary', 'likes', 'movies', 'too.']
2. ['John', 'also', 'likes', 'to', 'watch', 'football', 'games']

Ezenkívül minden mondatnál távolítsa el a szó több előfordulását, és használja a szószámot ennek képviseletére.

1. {"John":1,"likes":2,"to":1,"watch":1,"movies":2,"Mary":1,"too":1}
2. {"John":1,"also":1,"likes":1,"to":1,"watch":1,"football":1, "games":1}

Feltéve, hogy ezek a mondatok egy dokumentum részét képezik, az alábbiakban a teljes dokumentumunk egyesített szófrekvenciája látható. Mindkét mondatot figyelembe vesszük.

 {"John":2,"likes":3,"to":2,"watch":2,"movies":2,"Mary":1,"too":1, "also":1,"football":1,"games":1}

A fenti szókincset a dokumentumban szereplő összes szóból, a megfelelő szavak számával, felhasználjuk az egyes mondatok vektorainak létrehozásához.

A vektor hossza mindig megegyezik a szókincs méretével. Ebben az esetben a vektor hossza 11.

Annak érdekében, hogy eredeti mondatainkat vektorban ábrázolhassuk, minden vektorot minden nullával inicializálunk - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Ezt követi az iteráció és az összehasonlítás a szókincsünk minden egyes szavával, és a vektorérték növelése, ha a mondatban szerepel ez a szó.

John likes to watch movies. Mary likes movies too.[1, 2, 1, 1, 2, 1, 1, 0, 0, 0]
John also likes to watch football games.[1, 1, 1, 1, 0, 0, 0, 1, 1, 1]

Például az 1. mondatban a szó likesmásodik helyen jelenik meg, és kétszer jelenik meg. Tehát az 1. mondat vektorának második eleme 2 lesz: [1, 2, 1, 1, 2, 1, 1, 0, 0, 0]

A vektor mindig arányos a szókincsünk méretével.

Egy nagy dokumentum, ahol a generált szókincs hatalmas, sok 0 értékű vektort eredményezhet. Ezt ritka vektornak nevezzük .A ritka vektorok több memóriát és számítási erőforrást igényelnek a modellezés során. A nagyszámú pozíció vagy dimenzió nagyon kihívást jelenthet a modellezési folyamat számára a hagyományos algoritmusok számára.

BOW algoritmusunk kódolása

A kódunk bevitele több mondat lesz, a kimenet pedig a vektorok.

A bemeneti tömb a következő:

["Joe waited for the train", "The train was late", "Mary and Samantha took the bus",
"I looked for Mary and Samantha at the bus station",
"Mary and Samantha arrived at the bus station early but waited until noon for the bus"]

1. lépés: Tokenize egy mondatot

Kezdjük azzal, hogy eltávolítjuk a stopszavakat a mondatokból.

A stopszavak olyan szavak, amelyek nem tartalmaznak elegendő jelentőséget ahhoz, hogy algoritmusunk nélkül használhassuk őket. Nem szeretnénk, ha ezek a szavak helyet foglalnának az adatbázisunkban, vagy értékes feldolgozási időt igényelnének. Ehhez könnyedén eltávolíthatjuk őket azáltal, hogy tárolunk egy listát azokról a szavakról, amelyeket ön megállító szavaknak tart.

Tokenizálás a cselekmény szakítás sorozata húrok darabokra, mint a szavak, a kulcsszavak, kifejezések, szimbólumok és egyéb elemek az úgynevezett token . A tokenek lehetnek egyes szavak, kifejezések vagy akár egész mondatok. A tokenizálás során néhány karakter, például az írásjelek elvetésre kerülnek.

def word_extraction(sentence): ignore = ['a', "the", "is"] words = re.sub("[^\w]", " ", sentence).split() cleaned_text = [w.lower() for w in words if w not in ignore] return cleaned_text

A stopszavak erőteljesebb megvalósításához használhatja a python nltk könyvtárat. Nyelvenként előre meghatározott szavakkal rendelkezik. Íme egy példa:

import nltkfrom nltk.corpus import stopwords set(stopwords.words('english'))

2. lépés: Jelölést alkalmazzon az összes mondatra

def tokenize(sentences): words = [] for sentence in sentences: w = word_extraction(sentence) words.extend(w) words = sorted(list(set(words))) return words

A módszer az összes mondatot megismétli, és a kivont szót hozzáadja egy tömbhöz.

Ennek a módszernek a kimenete a következő lesz:

['and', 'arrived', 'at', 'bus', 'but', 'early', 'for', 'i', 'joe', 'late', 'looked', 'mary', 'noon', 'samantha', 'station', 'the', 'took', 'train', 'until', 'waited', 'was']

3. lépés: Készítsen szókincset és generáljon vektorokat

Az 1. és 2. lépésben meghatározott módszerekkel hozza létre a dokumentum szókincsét, és vonja ki a szavakat a mondatokból.

def generate_bow(allsentences): vocab = tokenize(allsentences) print("Word List for Document \n{0} \n".format(vocab));
for sentence in allsentences: words = word_extraction(sentence) bag_vector = numpy.zeros(len(vocab)) for w in words: for i,word in enumerate(vocab): if word == w: bag_vector[i] += 1 print("{0}\n{1}\n".format(sentence,numpy.array(bag_vector)))

Itt van a kódunk definiált bevitele és végrehajtása:

allsentences = ["Joe waited for the train train", "The train was late", "Mary and Samantha took the bus",
"I looked for Mary and Samantha at the bus station",
"Mary and Samantha arrived at the bus station early but waited until noon for the bus"]
generate_bow(allsentences)

Az egyes mondatok kimeneti vektorai:

Output:
Joe waited for the train train[0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 2. 0. 1. 0.]
The train was late[0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 1.]
Mary and Samantha took the bus[1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 1. 0. 0. 0. 0.]
I looked for Mary and Samantha at the bus station[1. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0.]
Mary and Samantha arrived at the bus station early but waited until noon for the bus[1. 1. 1. 2. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1. 0. 0. 0. 1. 1. 0.]

As you can see, each sentence was compared with our word list generated in Step 1. Based on the comparison, the vector element value may be incremented. These vectors can be used in ML algorithms for document classification and predictions.

We wrote our code and generated vectors, but now let’s understand bag of words a bit more.

Insights into bag of words

The BOW model only considers if a known word occurs in a document or not. It does not care about meaning, context, and order in which they appear.

This gives the insight that similar documents will have word counts similar to each other. In other words, the more similar the words in two documents, the more similar the documents can be.

Limitations of BOW

  1. Semantic meaning: the basic BOW approach does not consider the meaning of the word in the document. It completely ignores the context in which it’s used. The same word can be used in multiple places based on the context or nearby words.
  2. Vector size: For a large document, the vector size can be huge resulting in a lot of computation and time. You may need to ignore words based on relevance to your use case.

This was a small introduction to the BOW method. The code showed how it works at a low level. There is much more to understand about BOW. For example, instead of splitting our sentence in a single word (1-gram), you can split in the pair of two words (bi-gram or 2-gram). At times, bi-gram representation seems to be much better than using 1-gram. These can often be represented using N-gram notation. I have listed some research papers in the resources section for more in-depth knowledge.

You do not have to code BOW whenever you need it. It is already part of many available frameworks like CountVectorizer in sci-kit learn.

Our previous code can be replaced with:

from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer()X = vectorizer.fit_transform(allsentences)print(X.toarray())

It’s always good to understand how the libraries in frameworks work, and understand the methods behind them. The better you understand the concepts, the better use you can make of frameworks.

Thanks for reading the article. The code shown is available on my GitHub.

You can follow me on Medium, Twitter, and LinkedIn, For any questions, you can reach out to me on email (praveend806 [at] gmail [dot] com).

Resources to read more on bag of words

  1. Wikipedia-BOW
  2. Understanding Bag-of-Words Model: A Statistical Framework
  3. Semantics-Preserving Bag-of-Words Models and Applications