Токенизация корпуса из 10 документов в Python - PullRequest
0 голосов
/ 18 октября 2019

Я новичок в кодировании на Python, поэтому выяснение того, как кодировать более сложные действия, стало для меня проблемой.

Мое задание - вычислить TF-IDF из 10 документов. Но я застрял на том, как токенизировать корпус и распечатать количество жетонов и количество уникальных жетонов.

Если кто-то может помочь или даже сделать шаг, направляющий меня в правильном направлении, это было бы очень признательно!

Ответы [ 2 ]

0 голосов
/ 19 октября 2019

Я довольно забавно подошел к этому. Я использую те же данные, что и предоставленный @the_good_pony, поэтому я буду использовать тот же путь.

Мы будем использовать модули os и re, потому что регулярные выражения забавны и сложны!

import os
import re

# Path to where our data is located
base_Path = r'C:\location\to\folder\with\document\files


# Instantiate an empty dictonary
ddict = {}

# were going to walk our directory
for root, subdirs, filename in os.walk(base_path):
    # For each sub directory ('neg' and 'pos,' in this case)
    for d in subdirs:
        # Create a NEW dictionary with the subdirectory name as key
        ddict[d] = {}

        # Create a path to the subdirectory
        subroot = os.path.join(root, d)

        # Get a list of files for the directory
        # Save time by creating a new path for each file
        file_list = [os.path.join(subroot, i) for i in os.listdir(subroot) if i.endswith('txt')]

        # For each file in the filelist, open and read the file into the
        # subdictionary
        for f in file_list:
            # Basename = root name of path to file, or the filename
            fkey = os.path.basename(f)

            # Read file and set as subdictionary value
            with open(f, 'r') as f:
                ddict[d][fkey] = f.read()
            f.close()

Примеры отсчетов:

len(ddict.keys()) # 2 top-level subdirectories
len(ddict['neg'].keys()) # 1000 files in our 'neg' subdirectory
len(ddict['pos'].keys()) # 1000 files in our 'pos' subdirectory

# sample file content
# use two keys (subdirectory name and filename)

dirkey = 'pos'
filekey = 'cv000_29590.txt'
test1 = ddict[dirkey][filekey]

Вывод:

'films adapted from comic books have had plenty of success , whether they\'re about superheroes ( batman , superman , spawn ) , o [...]'


### Simple counter dictionary function
def val_counter(iterable, output_dict=None):
    # Instanciate a new dictionary
    if output_dict is None:
        output_dict = dict()

    # Check if element in dictionary
    # Add 1 if yes, or set to 1 if no
    for i in iterable:
        if i in output_dict.keys():
            output_dict[i] += 1
        else:
            output_dict[i] = 1
    return output_dict

Используя регулярные выражения, которые я перебил здесь, мы можем очистить наш текст от каждого корпуса и захватить буквенно-цифровые элементыв список. Я добавил опцию для включения маленьких слов (в данном случае 1 символ), но получение стоп-слов не было бы слишком сложным.

def wordcounts(corpus, dirname='pos', keep_small_words=False, count_dict=None):
    if count_dict is None:
        count_dict = dict()

    get_words_pat = r'(?:\s*|\n*|\t*)?([\w]+)(?:\s*|\n*|\t*)?'
    p = re.compile(get_words_pat)

    def clean_corpus(x):
        # Replace all whitespace with single-space
        clear_ws_pat = r'\s+'
        # Find nonalphanumeric characters
        remove_punc_pat = r'[^\w+]'


        tmp1 = re.sub(remove_punc_pat, ' ', x)

        # Respace whitespace and return
        return re.sub(clear_ws_pat, ' ', tmp1)

    # List of our files from the subdirectory
    keylist = list(corpus[dirname])


    for k in keylist:
        cleand = clean_corpus(corpus[dirname][k])

        # Tokenize based on size
        if keep_small_words:
            tokens = p.findall(cleand)
        else:
            # limit to results > 1 char in length
            tokens = [i for i in p.findall(cleand) if len(i) > 1]


        for i in tokens:
            if i in count_dict.keys():
                count_dict[i] += 1
            else:
                count_dict[i] = 1

    # Return dictionary once complete
    return count_dict



### Dictionary sorted lambda function

dict_sort = lambda d, descending=True: dict(sorted(d.items(), key=lambda x: x[1], reverse=descending))

# Run our function for positive corpus values
pos_result_dict = wordcounts(ddict, 'pos')
pos_result_dict = dict_sort(pos_result_dict)

Окончательная обработка и печать:

# Create dictionary of how frequent each count value is
freq_dist = val_counter(pos_result_dict.values())
freq_dist = dict_sort(freq_dist)


# Stats functions
k_count = lambda x: len(x.keys())
sum_vals = lambda x: sum([v for k, v in x.items()])
calc_avg = lambda x: sum_vals(x) / k_count(x)

# Get mean (arithmetic average) of word counts
mean_dict = calc_avg(pos_result_dict)

# Top-half of results.  We count shrink this even further, if necessary
top_dict = {k:v for k, v in pos_result_dict.items() if v >= mean_dict}

# This is probably your TD-IDF part
tot_count= sum([v for v in top_dict.values()])
for k, v in top_dict.items():
    pct_ = round(v / tot_count, 4)
    print('Word: ', k, ', count: ', v, ', %-age: ', pct_)
0 голосов
/ 19 октября 2019

Это может помочь.

У меня есть коллекция отдельных текстовых файлов, которые я хочу использовать и преобразовать в TfidfVectorizer. Это будет проходить через процесс приема файлов и использования TfidfVectorizer.

Я пошел к kaggle , чтобы получить некоторые примеры данных о рецензиях на фильмы

Я использовал негатив (neg) отзывы. Для моих целей не имеет значения, что это за данные, мне просто нужны текстовые данные.

Импорт необходимых пакетов

import pandas as pd 
import glob
from sklearn.feature_extraction.text import TfidfVectorizer

Как будут использоваться эти пакеты?

  • мы собираемся использовать панды для подготовки данных для TfidfVectorizer

  • glob будет использоваться для сбора местоположений каталога файлов

  • TfidfVectorizer является звездой шоу

Соберите местоположения файлов, используя Glob

ls_documents = [] 
for name in glob.glob('/location/to/folder/with/document/files/*'):
    ls_documents.append(name)

Это создаст список файловместах.

Считать данные из первых 10 файлов

ls_text = []
for document in ls_documents[:10]:
    f = open(document,"r")
    ls_text.append(f.read())

Теперь у нас есть список текста.

Импорт в панды

df_text = pd.DataFrame(ls_text)

Переименоватьстолбец, чтобы было легче работать с

df_text.columns = ['raw_text']

Очистите данные, удалив все строки с пустыми значениями

df_text['clean_text'] = df_text['raw_text'].fillna('')

Возможно, вы захотите выполнить другую очистку. Полезно сохранять необработанные данные и создавать отдельные «чистые» столбцы.

Создайте объект tfidf - я собираюсь снабдить его английскими стоп-словами

tfidf = TfidfVectorizer(stop_words='english')

подогнать и преобразовать созданный выше clean_text, передав tfidf серию clean_text

tfidf_matrix = tfidf.fit_transform(df_text['clean_text'])

Вы можете увидеть названия элементов из tfidf

tfidf.get_feature_names()

Вы увидите что-то похожее на это

['10',
 '13',
 '14',
 '175',
 '1960',
 '1990s',
 '1997',
 '20',
 '2001',
 '20th',
 '2176',
 '60',
 '80',
 '8mm',
 '90',
 '90s',
 '_huge_',
 'aberdeen',
 'able',
 'abo',
 'accent',
 'accentuate',
 'accident',
 'accidentally',
 'accompany',
 'accurate',
 'accused',
 'acting',
 'action',
 'actor',
....
]

Вы можете посмотреть на форму матрицы

tfidf_matrix.shape

В моем примере я получаю форму

(10, 1733)

Примерно это означает, что 1733 слова (то есть токены) описывают 10 документов

Не уверен, что выв этом вам могут пригодиться две статьи.

  • Эта статья от DataCamp использует tfidf в системе рекомендаций

  • Эта статья от DataCamp содержит некоторые общие методы обработки НЛП

...