ChatGPT解决这个技术问题 Extra ChatGPT

What does Keras Tokenizer method exactly do?

On occasion, circumstances require us to do the following:

from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(num_words=my_max)

Then, invariably, we chant this mantra:

tokenizer.fit_on_texts(text) 
sequences = tokenizer.texts_to_sequences(text)

While I (more or less) understand what the total effect is, I can't figure out what each one does separately, regardless of how much research I do (including, obviously, the documentation). I don't think I've ever seen one without the other.

So what does each do? Are there any circumstances where you would use either one without the other? If not, why aren't they simply combined into something like:

sequences = tokenizer.fit_on_texts_to_sequences(text)

Apologies if I'm missing something obvious, but I'm pretty new at this.

What I find to be counter-intuitive is that the Tokenizer's output is a sequence of integers, like word indices, rather than a list of individual tokens. In fact, it could take tokenized text (list of tokens for each content), and output the sequence of integers tensorflow.org/api_docs/python/tf/keras/preprocessing/text/….

n
nuric

From the source code:

fit_on_texts Updates internal vocabulary based on a list of texts. This method creates the vocabulary index based on word frequency. So if you give it something like, "The cat sat on the mat." It will create a dictionary s.t. word_index["the"] = 1; word_index["cat"] = 2 it is word -> index dictionary so every word gets a unique integer value. 0 is reserved for padding. So lower integer means more frequent word (often the first few are stop words because they appear a lot). texts_to_sequences Transforms each text in texts to a sequence of integers. So it basically takes each word in the text and replaces it with its corresponding integer value from the word_index dictionary. Nothing more, nothing less, certainly no magic involved.

Why don't combine them? Because you almost always fit once and convert to sequences many times. You will fit on your training corpus once and use that exact same word_index dictionary at train / eval / testing / prediction time to convert actual text into sequences to feed them to the network. So it makes sense to keep those methods separate.


So this was all in the source code! I guess I didn't look hard enough... And now I get it: fit - once, sequence - many! Live and learn, as usual. Thanks.
@nuric thanks for the reply. A few notes, however. According to official docs, "0 is a reserved index that won't be assigned to any word." so in your example first word index would be 1 keras.io/preprocessing/text Another point is that the default filter removes most of the punctuation symbols hence those will be the most frequent in vocabulary only when you remove punctuations from filter.
@Nikita thanks for pointing that out, I updated the answer to fix that.
Thank you. So, given a time series, do we have to tokenize it using Tokenizer please?
Can we extract words after doing fit_on_sequences
a
ajaysinghnegi

Adding more to above answers with examples will help in better understanding:

Example 1:

t  = Tokenizer()
fit_text = "The earth is an awesome place live"
t.fit_on_texts(fit_text)
test_text = "The earth is an great place live"
sequences = t.texts_to_sequences(test_text)

print("sequences : ",sequences,'\n')

print("word_index : ",t.word_index)
#[] specifies : 1. space b/w the words in the test_text    2. letters that have not occured in fit_text

Output :

       sequences :  [[3], [4], [1], [], [1], [2], [8], [3], [4], [], [5], [6], [], [2], [9], [], [], [8], [1], [2], [3], [], [13], [7], [2], [14], [1], [], [7], [5], [15], [1]] 

       word_index :  {'e': 1, 'a': 2, 't': 3, 'h': 4, 'i': 5, 's': 6, 'l': 7, 'r': 8, 'n': 9, 'w': 10, 'o': 11, 'm': 12, 'p': 13, 'c': 14, 'v': 15}

Example 2:

t  = Tokenizer()
fit_text = ["The earth is an awesome place live"]
t.fit_on_texts(fit_text)

#fit_on_texts fits on sentences when list of sentences is passed to fit_on_texts() function. 
#ie - fit_on_texts( [ sent1, sent2, sent3,....sentN ] )

#Similarly, list of sentences/single sentence in a list must be passed into texts_to_sequences.
test_text1 = "The earth is an great place live"
test_text2 = "The is my program"
sequences = t.texts_to_sequences([test_text1, test_text2])

print('sequences : ',sequences,'\n')

print('word_index : ',t.word_index)
#texts_to_sequences() returns list of list. ie - [ [] ]

Output:

        sequences :  [[1, 2, 3, 4, 6, 7], [1, 3]] 

        word_index :  {'the': 1, 'earth': 2, 'is': 3, 'an': 4, 'awesome': 5, 'place': 6, 'live': 7}

Examples never lie! Thanks for the great answer.
I have a training dataset and a test dataset both have two columns: an index and the text already cleaned. I am wondering if it is ok to do an append() between both dataframes and then do Tokenizer.fit_on_text () on the appended set, rather than just doing it on the training one. I think if all I want is to convert text into an integer vector where each integer represents a word from all the vocabulary used, doing an append() first would be better because the vectors in the test set will have more elements when I do text_to_sequence().
d
desertnaut

Lets see what this line of code does.

tokenizer.fit_on_texts(text) 

For example, consider the sentence " The earth is an awesome place live"

tokenizer.fit_on_texts("The earth is an awesome place live") fits [[1,2,3,4,5,6,7]] where 3 -> "is" , 6 -> "place", so on.

sequences = tokenizer.texts_to_sequences("The earth is an great place live")

returns [[1,2,3,4,6,7]].

You see what happened here. The word "great" is not fit initially, so it does not recognize the word "great". Meaning, fit_on_text can be used independently on train data and then the fitted vocabulary index can be used to represent a completely new set of word sequence. These are two different processes. Hence the two lines of code.


Good catch about the missing word 'great'. But how can we deal with such words which are not in the vocabulary?
G
Gennaro

nuric already satistified the question, but I would add something.

Please focus on both word frequency-based encoding and OOV in this example:

from tensorflow.keras.preprocessing.text        import Tokenizer

corpus =['The', 'cat', 'is', 'on', 'the', 'table', 'a', 'very', 'long', 'table']

tok_obj = Tokenizer(num_words=10, oov_token='<OOV>')
tok_obj.fit_on_texts(corpus)

[TL;DR] The tokenizer will include the first 10 words appearing in the corpus. Here 10 words, but only 8 are unique. The most frequent 10 words will be encoded, if they are more than this number they will go OOV (Out Of Vocabulary).

Built dictionary:

Please note the frequency

{'<OOV>': 1, 'the': 2, 'table': 3, 'cat': 4, 'is': 5, 'on': 6, 'a': 7, 'very': 8, 'long': 9}

Sentence(s) processing:

processed_seq = tok_obj.texts_to_sequences(['The dog is on the bed'])

Which gives:

>>> processed_seq
    [[2, 1, 5, 6, 2, 1]]

How to retrieve the sentence?

Build the dictionary inv_map and use It! list comprehension can be used below to compress the code.

inv_map = {v: k for k, v in tok_obj.word_index.items()}

for seq in processed_seq:
    for tok in seq:
        print(inv_map[tok])

which gives:

>>> the
<OOV>
is
on
the
<OOV>

because dog and bed are not in the dictionary.

List comprehension can be used to compress the code. Here obtaining a list as output.

[inv_map[tok] for seq in processed_seq for tok in seq]

which gives:

>>> ['the', '<OOV>', 'is', 'on', 'the', '<OOV>']