Używam NLTK do wyszukiwania n-gramów w korpusie, ale w niektórych przypadkach zajmuje to bardzo dużo czasu. Zauważyłem, że obliczanie n-gramów nie jest rzadką cechą w innych pakietach (najwyraźniej Haystack ma jakąś funkcjonalność). Czy to oznacza, że istnieje potencjalnie szybszy sposób na znalezienie n-gramów w moim korpusie, jeśli zrezygnuję z NLTK? Jeśli tak, to w czym mogę przyspieszyć działanie?Szybkie obliczenia n-graficzne
Odpowiedz
Ponieważ nie wskazałeś, czy chcesz n-gramów na słowo, czy na poziomie postaci, po prostu przyjmiemy to pierwsze, bez utraty ogólności.
Zakładam też, że zaczynasz od listy tokenów, reprezentowanych przez ciągi. To, co możesz łatwo zrobić, to samemu napisać n-gramową ekstrakcję.
def ngrams(tokens, MIN_N, MAX_N):
n_tokens = len(tokens)
for i in xrange(n_tokens):
for j in xrange(i+MIN_N, min(n_tokens, i+MAX_N)+1):
yield tokens[i:j]
Następnie wymień yield
z faktycznym działaniem chcesz wziąć na każdy n-gram (dodaj go do dict
, należy go przechowywać w bazie danych, cokolwiek), aby pozbyć się napowietrznej generatora.
Wreszcie, jeśli naprawdę nie jest wystarczająco szybki, zamień powyższy kod na Cython i skompiluj go. Przykład z użyciem defaultdict
zamiast yield
:
def ngrams(tokens, int MIN_N, int MAX_N):
cdef Py_ssize_t i, j, n_tokens
count = defaultdict(int)
join_spaces = " ".join
n_tokens = len(tokens)
for i in xrange(n_tokens):
for j in xrange(i+MIN_N, min(n_tokens, i+MAX_N)+1):
count[join_spaces(tokens[i:j])] += 1
return count
Nowsze wersje Cython rozpoznają w Pythonie instrukcje i przyspieszają je, jeśli to możliwe. Ponadto w wewnętrznej iteracji znajduje się odnośnik do metody. zdefiniowanie 'tokenjoiner = "" .join' poza pętlą i zastąpienie wewnętrznego ".join powinno przyspieszyć działanie. – rocksportrocker
@rocksportrocker: dobre miejsce, dodano Twoją sugestię. –
i można przepisać wewnętrzną linię za pomocą "count.get (....) + = 1" wprowadzić inny var, aby uniknąć wyszukiwania metod. – rocksportrocker
Można znaleźć pythonic, elegancki i szybki funkcję generacji Ngram użyciu zip
i ikona (*) operatora here:
def find_ngrams(input_list, n):
return zip(*[input_list[i:] for i in range(n)])
Na znak poziomu N- gramów można użyć następującą funkcję:
def ngrams(text, n):
n-=1
return [text[i-n:i+1] for i,char in enumerate(text)][n:]
- 1. Szybkie i wydajne obliczenia na tablicach
- 2. Szybkie rekursje Fibonacciego
- 3. Szybkie odwracanie macierzy bez pakietu
- 4. Szybkie i precyzyjne powtarzanie Pythona
- 5. Szybkie obliczanie kwadratu binarnego
- 6. Standardy zaokrąglania - Obliczenia finansowe
- 7. obliczenia zaokrąglone w cobol
- 8. obliczenia symboliczne w C++
- 9. Obliczenia ograniczające w Haskell
- 10. Obliczenia na koniec miesiąca
- 11. Obliczenia Firebuga i Offsetu
- 12. Memoizing IO Obliczenia Haskell
- 13. Obliczenia za pomocą COUNT()
- 14. Obliczenia PHP są błędne
- 15. Równoległe obliczenia w Haskell
- 16. Obliczenia gradientowe z pytonem
- 17. Szybkie algorytmy do wyszukiwania parami odległości euklidesowej
- 18. Szybkie wykrywanie punktów subpikselowych laserowych
- 19. szybkie obliczanie macierzy jądra w R
- 20. KVC a szybkie wyliczenie
- 21. Szybkie przechwytywanie stosu wywołań
- 22. Szybkie przechwytywanie ekranu Java
- 23. Polecenie gitbash szybkie odwołanie
- 24. Szybkie ciąg tablicą - Cython
- 25. Szybkie sortowanie tabeli HTML?
- 26. C# szybkie renderowanie pikseli
- 27. Szybkie wyszukiwanie plików TypeScript
- 28. Szybkie rozpakowywanie dla ASP.NET
- 29. Szybkie sortowanie w Haskell
- 30. Szybkie rozwiązywanie anagramów
Więcej informacji dla zainteresowanych: http://packages.python.org/Whoosh/ngram s.html – Trindaz
Powiązane pytanie: http://stackoverflow.com/questions/21883108/fast-optimize-n-gram-implementations-in-python – dmcc