পাইথনে এন-গ্রাম, চার, পাঁচ, ছয় গ্রাম?


137

আমি কোনও পাঠ্যকে এন-গ্রামে বিভক্ত করার উপায় খুঁজছি। সাধারণত আমি এমন কিছু করতাম:

import nltk
from nltk import bigrams
string = "I really like python, it's pretty awesome."
string_bigrams = bigrams(string)
print string_bigrams

আমি জানি যে এনল্টক কেবল বিগ্রাম এবং ট্রিগার সরবরাহ করে তবে আমার পাঠ্যকে চার-গ্রাম, পাঁচ-গ্রাম বা এমনকি শত-গ্রামে ভাগ করার কোনও উপায় আছে কি?

ধন্যবাদ!


আপনি কি শব্দটি বা অক্ষর দ্বারা পাঠ্যটিকে এন আকারের গ্রুপে বিভক্ত করতে চান? উপরেরটির জন্য কী আউটপুট দেখতে হবে তার একটি উদাহরণ দিতে পারেন?
ক্রিসপ্রেসার

4
কখনও এনল্টকে করেনি তবে দেখে মনে হচ্ছে এমন কোনও ফাংশন রয়েছে ingramsযার দ্বিতীয় প্যারামিটারটি আপনি চান এনজিগ্রামের ডিগ্রি। কি এই nltk আপনি ব্যবহার করছেন সংস্করণ? এমনকি যদি না, এখানে উৎস সম্পাদনা করুন: নেই ngramsএবং ingramsসেখানে, ingramsজেনারেটরের হচ্ছে।
ব্রায়ান

: এছাড়া এই থ্রেড যে দরকারী হতে পারে অধীনে একটি উত্তর stackoverflow.com/questions/7591258/fast-n-gram-calculation
ChrisProsser

উত্তর:


212

অন্যান্য ব্যবহারকারীদের দ্বারা দেওয়া দুর্দান্ত দেশীয় অজগর ভিত্তিক উত্তর। তবে এখানেnltk পদ্ধতির (কেবলমাত্র nltkলাইব্রেরিতে ইতিমধ্যে যা রয়েছে তা পুনর্নবীকরণের জন্য ওপি শাস্তি পেয়েছে )।

এমন একটি এনজিআর মডিউল রয়েছে যা লোকেরা খুব কমই ব্যবহার করে nltk। এটি এনজিগ্রামগুলি পড়া কঠিন বলে নয়, তবে এনজিআরমে একটি মডেল বেসকে প্রশিক্ষণ দেওয়া যেখানে এন> 3 এর ফলে অনেকগুলি ডেটা স্পারসিটি হবে।

from nltk import ngrams

sentence = 'this is a foo bar sentences and i want to ngramize it'

n = 6
sixgrams = ngrams(sentence.split(), n)

for grams in sixgrams:
  print grams

4
চরিত্র ngrams জন্য, দয়া করে আরো তাকান: stackoverflow.com/questions/22428020/...
alvas

সম্পূর্ণ ডকুমেন্ট যেমন টেক্সট হিসাবে পরীক্ষা করতে এন-গ্রাম ব্যবহার করার কোনও উপায় আছে? আমি পাইথনের সাথে পরিচিত নই তাই আমি জানি না এটি কোনও টেক্সট ফাইল খুলতে পারে এবং তারপরে এটি পরীক্ষা করার জন্য এন-গ্রাম বিশ্লেষণ ব্যবহার করতে পারে?
maoyi

1
কীভাবে কেউ নির্ভুলতা পরীক্ষা করতে পারেন মন্তব্য করতে পারেন sixgrams?
LYu

64

আমি অবাক হয়েছি যে এটি এখনও প্রদর্শিত হয়নি:

In [34]: sentence = "I really like python, it's pretty awesome.".split()

In [35]: N = 4

In [36]: grams = [sentence[i:i+N] for i in xrange(len(sentence)-N+1)]

In [37]: for gram in grams: print gram
['I', 'really', 'like', 'python,']
['really', 'like', 'python,', "it's"]
['like', 'python,', "it's", 'pretty']
['python,', "it's", 'pretty', 'awesome.']

ঠিক এই প্রথম উত্তরটি ফ্রিকোয়েন্সি গণনা এবং টিউপল রূপান্তর বিয়োগ করে।
ব্রায়ান

যদিও এটি একটি বোধগম্যতা হিসাবে আবার লিখেছে দেখতে ভাল লাগছে।
ব্রায়ান

@ এমিরোচে: ভাল ক্যাচ বাগ রিপোর্টের জন্য ধন্যবাদ। এটি এখনই ঠিক করা হয়েছে
ইন্সপেক্টর

16

কেবল এনল্টেকে সরঞ্জাম ব্যবহার করা

from nltk.tokenize import word_tokenize
from nltk.util import ngrams

def get_ngrams(text, n ):
    n_grams = ngrams(word_tokenize(text), n)
    return [ ' '.join(grams) for grams in n_grams]

উদাহরণ আউটপুট

get_ngrams('This is the simplest text i could think of', 3 )

['This is the', 'is the simplest', 'the simplest text', 'simplest text i', 'text i could', 'i could think', 'could think of']

অ্যারে ফর্ম্যাটে এনজিআমগুলি রাখার জন্য কেবল অপসারণ করুন ' '.join


15

এন-গ্রাম করার জন্য এখানে আরও একটি সহজ উপায়

>>> from nltk.util import ngrams
>>> text = "I am aware that nltk only offers bigrams and trigrams, but is there a way to split my text in four-grams, five-grams or even hundred-grams"
>>> tokenize = nltk.word_tokenize(text)
>>> tokenize
['I', 'am', 'aware', 'that', 'nltk', 'only', 'offers', 'bigrams', 'and', 'trigrams', ',', 'but', 'is', 'there', 'a', 'way', 'to', 'split', 'my', 'text', 'in', 'four-grams', ',', 'five-grams', 'or', 'even', 'hundred-grams']
>>> bigrams = ngrams(tokenize,2)
>>> bigrams
[('I', 'am'), ('am', 'aware'), ('aware', 'that'), ('that', 'nltk'), ('nltk', 'only'), ('only', 'offers'), ('offers', 'bigrams'), ('bigrams', 'and'), ('and', 'trigrams'), ('trigrams', ','), (',', 'but'), ('but', 'is'), ('is', 'there'), ('there', 'a'), ('a', 'way'), ('way', 'to'), ('to', 'split'), ('split', 'my'), ('my', 'text'), ('text', 'in'), ('in', 'four-grams'), ('four-grams', ','), (',', 'five-grams'), ('five-grams', 'or'), ('or', 'even'), ('even', 'hundred-grams')]
>>> trigrams=ngrams(tokenize,3)
>>> trigrams
[('I', 'am', 'aware'), ('am', 'aware', 'that'), ('aware', 'that', 'nltk'), ('that', 'nltk', 'only'), ('nltk', 'only', 'offers'), ('only', 'offers', 'bigrams'), ('offers', 'bigrams', 'and'), ('bigrams', 'and', 'trigrams'), ('and', 'trigrams', ','), ('trigrams', ',', 'but'), (',', 'but', 'is'), ('but', 'is', 'there'), ('is', 'there', 'a'), ('there', 'a', 'way'), ('a', 'way', 'to'), ('way', 'to', 'split'), ('to', 'split', 'my'), ('split', 'my', 'text'), ('my', 'text', 'in'), ('text', 'in', 'four-grams'), ('in', 'four-grams', ','), ('four-grams', ',', 'five-grams'), (',', 'five-grams', 'or'), ('five-grams', 'or', 'even'), ('or', 'even', 'hundred-grams')]
>>> fourgrams=ngrams(tokenize,4)
>>> fourgrams
[('I', 'am', 'aware', 'that'), ('am', 'aware', 'that', 'nltk'), ('aware', 'that', 'nltk', 'only'), ('that', 'nltk', 'only', 'offers'), ('nltk', 'only', 'offers', 'bigrams'), ('only', 'offers', 'bigrams', 'and'), ('offers', 'bigrams', 'and', 'trigrams'), ('bigrams', 'and', 'trigrams', ','), ('and', 'trigrams', ',', 'but'), ('trigrams', ',', 'but', 'is'), (',', 'but', 'is', 'there'), ('but', 'is', 'there', 'a'), ('is', 'there', 'a', 'way'), ('there', 'a', 'way', 'to'), ('a', 'way', 'to', 'split'), ('way', 'to', 'split', 'my'), ('to', 'split', 'my', 'text'), ('split', 'my', 'text', 'in'), ('my', 'text', 'in', 'four-grams'), ('text', 'in', 'four-grams', ','), ('in', 'four-grams', ',', 'five-grams'), ('four-grams', ',', 'five-grams', 'or'), (',', 'five-grams', 'or', 'even'), ('five-grams', 'or', 'even', 'hundred-grams')]

1
Nltk.word_tokenize () ফাংশনটি ব্যবহার করতে nltk.download ('punkt') করতে হয়েছিল। ফলাফলগুলি মুদ্রণের জন্য জেনারেটর অবজেক্টকে বিগ্রাম, ট্রাইগ্রাম এবং চারগ্রামের তালিকা হিসাবে তালিকাতে (<জেনারেটর_জেক্ট>) ব্যবহার করে রূপান্তর করতে হয়েছিল।
bhatman

11

লোকেরা ইতিমধ্যে সেই দৃশ্যের জন্য বেশ সুন্দর উত্তর দিয়েছে যেখানে আপনার বড়গ্রাম বা ট্রিগম প্রয়োজন তবে সেই ক্ষেত্রে বাক্যটির জন্য যদি আপনার প্রত্যেকের প্রয়োজন হয় তবে আপনি ব্যবহার করতে পারেনnltk.util.everygrams

>>> from nltk.util import everygrams

>>> message = "who let the dogs out"

>>> msg_split = message.split()

>>> list(everygrams(msg_split))
[('who',), ('let',), ('the',), ('dogs',), ('out',), ('who', 'let'), ('let', 'the'), ('the', 'dogs'), ('dogs', 'out'), ('who', 'let', 'the'), ('let', 'the', 'dogs'), ('the', 'dogs', 'out'), ('who', 'let', 'the', 'dogs'), ('let', 'the', 'dogs', 'out'), ('who', 'let', 'the', 'dogs', 'out')]

ট্রিগারের ক্ষেত্রে আপনার যেমন সীমা থাকে সেখানে সর্বাধিক দৈর্ঘ্য 3 হওয়া উচিত তবে আপনি এটি নির্দিষ্ট করতে ম্যাক্স_লেন পরম ব্যবহার করতে পারেন।

>>> list(everygrams(msg_split, max_len=2))
[('who',), ('let',), ('the',), ('dogs',), ('out',), ('who', 'let'), ('let', 'the'), ('the', 'dogs'), ('dogs', 'out')]

আপনি যে পরিমাণ গ্রাম অর্থাৎ চার গ্রাম, পাঁচ গ্রাম, ছয় বা এমনকি একশো গ্রাম তা অর্জন করতে আপনি সর্বাধিক_প্রেমটি পরিবর্তন করতে পারেন।

পূর্বের উল্লিখিত সমাধানগুলিতে উল্লিখিত সমাধানটি কার্যকর করতে পরিবর্তন করা যেতে পারে তবে এই সমাধানটি তার চেয়ে অনেক সোজা এগিয়ে forward

আরও পড়ার জন্য এখানে ক্লিক করুন

এবং যখন আপনার কেবলমাত্র বিগ্রাম বা ট্রাইগ্রাম ইত্যাদির মতো একটি নির্দিষ্ট গ্রাম প্রয়োজন হবে তখন আপনি এমএহসানের উত্তরে উল্লিখিত nltk.util.ngram ব্যবহার করতে পারেন ।


6

এটি ব্যবহার করে আপনি সহজেই নিজের ফাংশনটি হুইপ করতে পারেন itertools:

from itertools import izip, islice, tee
s = 'spam and eggs'
N = 3
trigrams = izip(*(islice(seq, index, None) for index, seq in enumerate(tee(s, N))))
list(trigrams)
# [('s', 'p', 'a'), ('p', 'a', 'm'), ('a', 'm', ' '),
# ('m', ' ', 'a'), (' ', 'a', 'n'), ('a', 'n', 'd'),
# ('n', 'd', ' '), ('d', ' ', 'e'), (' ', 'e', 'g'),
# ('e', 'g', 'g'), ('g', 'g', 's')]

1
আপনি দয়া করে ব্যাখ্যা করতে পারেন izip(*(islice(seq, index, None) for index, seq in enumerate(tee(s, N))))আমি এটি বেশ বুঝতে পারি না।
তোমাজস্টোয়েলজকোভিক

4

পাইথনের বিল্টিন সহ বিগ্রামগুলি তৈরি করার জন্য আরও মার্জিত পদ্ধতির zip()। কেবলমাত্র মূল স্ট্রিংটিকে একটি তালিকায় রূপান্তর করুন split(), তারপরে তালিকাটি একবারে সাধারণত পাস করুন এবং একবার কোনও উপাদান দ্বারা অফসেট করুন।

string = "I really like python, it's pretty awesome."

def find_bigrams(s):
    input_list = s.split(" ")
    return zip(input_list, input_list[1:])

def find_ngrams(s, n):
  input_list = s.split(" ")
  return zip(*[input_list[i:] for i in range(n)])

find_bigrams(string)

[('I', 'really'), ('really', 'like'), ('like', 'python,'), ('python,', "it's"), ("it's", 'pretty'), ('pretty', 'awesome.')]

2

আমি কখনই এনলটকের সাথে ডিল করি নি তবে কিছু ছোট শ্রেণির প্রকল্পের অংশ হিসাবে এন-গ্রাম করেছি। আপনি যদি স্ট্রিংটিতে থাকা সমস্ত এন-গ্রামগুলির ফ্রিকোয়েন্সি সন্ধান করতে চান তবে এটি করার একটি উপায় এখানে a Dআপনাকে আপনার এন-শব্দের হিস্টোগ্রাম দেবে।

D = dict()
string = 'whatever string...'
strparts = string.split()
for i in range(len(strparts)-N): # N-grams
    try:
        D[tuple(strparts[i:i+N])] += 1
    except:
        D[tuple(strparts[i:i+N])] = 1

collections.Counter(tuple(strparts[i:i+N]) for i in xrange(len(strparts)-N))ব্যতীত
ইন্সপেক্টর

2

চার_গ্রামের জন্য এটি ইতিমধ্যে এনএলটিকে রয়েছে , এখানে একটি কোডের টুকরো রয়েছে যা আপনাকে এটির পক্ষে সহায়তা করতে পারে:

 from nltk.collocations import *
 import nltk
 #You should tokenize your text
 text = "I do not like green eggs and ham, I do not like them Sam I am!"
 tokens = nltk.wordpunct_tokenize(text)
 fourgrams=nltk.collocations.QuadgramCollocationFinder.from_words(tokens)
 for fourgram, freq in fourgrams.ngram_fd.items():  
       print fourgram, freq

আমি আসা করি এটা সাহায্য করবে.


2

আপনি sklearn.feature_extration.text.CountVectorizer ব্যবহার করতে পারেন :

import sklearn.feature_extraction.text # FYI http://scikit-learn.org/stable/install.html
ngram_size = 4
string = ["I really like python, it's pretty awesome."]
vect = sklearn.feature_extraction.text.CountVectorizer(ngram_range=(ngram_size,ngram_size))
vect.fit(string)
print('{1}-grams: {0}'.format(vect.get_feature_names(), ngram_size))

আউটপুট:

4-grams: [u'like python it pretty', u'python it pretty awesome', u'really like python it']

আপনি ngram_sizeযেকোন ধনাত্মক পূর্ণসংখ্যায় সেট করতে পারেন । অর্থাৎ আপনি কোনও পাঠ্যকে চার-গ্রাম, পাঁচ-গ্রাম বা এমনকি শত-গ্রামে ভাগ করতে পারেন।


2

দক্ষতা যদি কোনও সমস্যা হয় এবং আপনাকে একাধিক বিভিন্ন এন-গ্রাম (আপনার যেমন বলা যায় তত একশত) বানাতে হয় তবে আপনি খাঁটি অজগরটি ব্যবহার করতে চান আমি যা করব:

from itertools import chain

def n_grams(seq, n=1):
    """Returns an itirator over the n-grams given a listTokens"""
    shiftToken = lambda i: (el for j,el in enumerate(seq) if j>=i)
    shiftedTokens = (shiftToken(i) for i in range(n))
    tupleNGrams = zip(*shiftedTokens)
    return tupleNGrams # if join in generator : (" ".join(i) for i in tupleNGrams)

def range_ngrams(listTokens, ngramRange=(1,2)):
    """Returns an itirator over all n-grams for n in range(ngramRange) given a listTokens."""
    return chain(*(n_grams(listTokens, i) for i in range(*ngramRange)))

ব্যবহার:

>>> input_list = input_list = 'test the ngrams generator'.split()
>>> list(range_ngrams(input_list, ngramRange=(1,3)))
[('test',), ('the',), ('ngrams',), ('generator',), ('test', 'the'), ('the', 'ngrams'), ('ngrams', 'generator'), ('test', 'the', 'ngrams'), ('the', 'ngrams', 'generator')]

N NLTK হিসাবে একই গতি:

import nltk
%%timeit
input_list = 'test the ngrams interator vs nltk '*10**6
nltk.ngrams(input_list,n=5)
# 7.02 ms ± 79 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
input_list = 'test the ngrams interator vs nltk '*10**6
n_grams(input_list,n=5)
# 7.01 ms ± 103 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
input_list = 'test the ngrams interator vs nltk '*10**6
nltk.ngrams(input_list,n=1)
nltk.ngrams(input_list,n=2)
nltk.ngrams(input_list,n=3)
nltk.ngrams(input_list,n=4)
nltk.ngrams(input_list,n=5)
# 7.32 ms ± 241 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
input_list = 'test the ngrams interator vs nltk '*10**6
range_ngrams(input_list, ngramRange=(1,6))
# 7.13 ms ± 165 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

আমার আগের উত্তর থেকে পোস্ট করুন


0

Nltk দুর্দান্ত তবে কিছু প্রকল্পের জন্য এটি কখনও কখনও ওভারহেড হয়:

import re
def tokenize(text, ngrams=1):
    text = re.sub(r'[\b\(\)\\\"\'\/\[\]\s+\,\.:\?;]', ' ', text)
    text = re.sub(r'\s+', ' ', text)
    tokens = text.split()
    return [tuple(tokens[i:i+ngrams]) for i in xrange(len(tokens)-ngrams+1)]

উদাহরণ ব্যবহার:

>> text = "This is an example text"
>> tokenize(text, 2)
[('This', 'is'), ('is', 'an'), ('an', 'example'), ('example', 'text')]
>> tokenize(text, 3)
[('This', 'is', 'an'), ('is', 'an', 'example'), ('an', 'example', 'text')]

0

আপনি নীচে অন্যান্য প্যাকেজ ছাড়াই কোড ব্যবহার করে সমস্ত 4-6 গ্রাম পেতে পারেন:

from itertools import chain

def get_m_2_ngrams(input_list, min, max):
    for s in chain(*[get_ngrams(input_list, k) for k in range(min, max+1)]):
        yield ' '.join(s)

def get_ngrams(input_list, n):
    return zip(*[input_list[i:] for i in range(n)])

if __name__ == '__main__':
    input_list = ['I', 'am', 'aware', 'that', 'nltk', 'only', 'offers', 'bigrams', 'and', 'trigrams', ',', 'but', 'is', 'there', 'a', 'way', 'to', 'split', 'my', 'text', 'in', 'four-grams', ',', 'five-grams', 'or', 'even', 'hundred-grams']
    for s in get_m_2_ngrams(input_list, 4, 6):
        print(s)

আউটপুট নীচে:

I am aware that
am aware that nltk
aware that nltk only
that nltk only offers
nltk only offers bigrams
only offers bigrams and
offers bigrams and trigrams
bigrams and trigrams ,
and trigrams , but
trigrams , but is
, but is there
but is there a
is there a way
there a way to
a way to split
way to split my
to split my text
split my text in
my text in four-grams
text in four-grams ,
in four-grams , five-grams
four-grams , five-grams or
, five-grams or even
five-grams or even hundred-grams
I am aware that nltk
am aware that nltk only
aware that nltk only offers
that nltk only offers bigrams
nltk only offers bigrams and
only offers bigrams and trigrams
offers bigrams and trigrams ,
bigrams and trigrams , but
and trigrams , but is
trigrams , but is there
, but is there a
but is there a way
is there a way to
there a way to split
a way to split my
way to split my text
to split my text in
split my text in four-grams
my text in four-grams ,
text in four-grams , five-grams
in four-grams , five-grams or
four-grams , five-grams or even
, five-grams or even hundred-grams
I am aware that nltk only
am aware that nltk only offers
aware that nltk only offers bigrams
that nltk only offers bigrams and
nltk only offers bigrams and trigrams
only offers bigrams and trigrams ,
offers bigrams and trigrams , but
bigrams and trigrams , but is
and trigrams , but is there
trigrams , but is there a
, but is there a way
but is there a way to
is there a way to split
there a way to split my
a way to split my text
way to split my text in
to split my text in four-grams
split my text in four-grams ,
my text in four-grams , five-grams
text in four-grams , five-grams or
in four-grams , five-grams or even
four-grams , five-grams or even hundred-grams

আপনি এই ব্লগে আরও বিস্তারিত জানতে পারেন


0

প্রায় সাত বছর পরে, এখানে ব্যবহার করে আরও মার্জিত উত্তর collections.deque:

def ngrams(words, n):
    d = collections.deque(maxlen=n)
    d.extend(words[:n])
    words = words[n:]
    for window, word in zip(itertools.cycle((d,)), words):
        print(' '.join(window))
        d.append(word)

words = ['I', 'am', 'become', 'death,', 'the', 'destroyer', 'of', 'worlds']

আউটপুট:

In [15]: ngrams(words, 3)                                                                                                                                                                                                                     
I am become
am become death,
become death, the
death, the destroyer
the destroyer of

In [16]: ngrams(words, 4)                                                                                                                                                                                                                     
I am become death,
am become death, the
become death, the destroyer
death, the destroyer of

In [17]: ngrams(words, 1)                                                                                                                                                                                                                     
I
am
become
death,
the
destroyer
of

In [18]: ngrams(words, 2)                                                                                                                                                                                                                     
I am
am become
become death,
death, the
the destroyer
destroyer of

0

আপনি যদি ধ্রুবক মেমরির ব্যবহার সহ বড় স্ট্রিংগুলির জন্য খাঁটি পুনরাবৃত্তি সমাধান চান:

from typing import Iterable  
import itertools

def ngrams_iter(input: str, ngram_size: int, token_regex=r"[^\s]+") -> Iterable[str]:
    input_iters = [ 
        map(lambda m: m.group(0), re.finditer(token_regex, input)) 
        for n in range(ngram_size) 
    ]
    # Skip first words
    for n in range(1, ngram_size): list(map(next, input_iters[n:]))  

    output_iter = itertools.starmap( 
        lambda *args: " ".join(args),  
        zip(*input_iters) 
    ) 
    return output_iter

টেস্ট:

input = "If you want a pure iterator solution for large strings with constant memory usage"
list(ngrams_iter(input, 5))

আউটপুট:

['If you want a pure',
 'you want a pure iterator',
 'want a pure iterator solution',
 'a pure iterator solution for',
 'pure iterator solution for large',
 'iterator solution for large strings',
 'solution for large strings with',
 'for large strings with constant',
 'large strings with constant memory',
 'strings with constant memory usage']
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.