Skocz do zawartości

Wyciąganie najczęściej występujących słów


Adam Krywko

Rekomendowane odpowiedzi

Jest sobie baza danych (200MB) zawierająca zdania (1 rekord - jedno zdanie).

Chciałbym uzyskać listę 100 najczęściej występujących w niej słów.

Chyba przyjdzie mi rozbijać te zdania i wrzucać do tabeli słowo/ilość_wystąpień

ale może ktoś już przerabiał ten temat i zna lepszą metodę? :jezyk1:

Jestem w potrzebie - sprzedaje
cenne domeny regionalne za ułamek wartości
tylko do końca tyg. < link do ogłoszenia >

Odnośnik do komentarza
Udostępnij na innych stronach

// tą tabelę już masz 200 MB
CREATE TABLE zdania 
(
id integer not null primary key,
zdanie varchar(1000)
)

CREATE TABLE slowa
(
id integer not null primary key,
slowo varchar(100)
)

CREATE TABLE slowa_zdania
(
 fk_slowa integer,
 fk_zdania integer,
 pozycja integer,
 ... ewentualne  dodatkowe pola FK np. dotyczące jaka to cześć mowy zdania itp. o ile potrzebne
)

Algorytm na budowanie słownika:

Dla kazdego wiersza zdania wykonuj:

-Podziel na słowa

-Sprawdz czy słowo jest w słowniku slowa , jak trzeba dodaj

-Zapisz w tabeli slowa_zdania wiersz

i potem to już tylko

SELECT  count(fk_slowa) , slowo FROM
slowa join slowa_zdania on  slowa.ID = slowa_zdania.fk_slowa
group by  slowo 
order by 1 DESC 
LIMIT 100

Do zastanowienia jest tylko to co dla Ciebie jest tym samym słowem a co innym, czy uwzgledniasz przypadki , osoby itp.

Czy też sprowadzasz słowo do formy podstawowej :jezyk1: Ale to już musisz sobie ustalić na poczatku.

Oczywiście można to wszystko zrobić na 100 innych sposobów np. z użyciem grep cat wc albo kawałka kodu PHP :tancze:

[edit] poprawiłem SQL bo znalazłem błąd i dodałem LIMIT 100

Odnośnik do komentarza
Udostępnij na innych stronach

Wybór metody powinien uwzględniać też następne kroki , bo znając już słowa jakie są najpopularniejsze może

chcielibyśmy poznać listę zdań jakie są z tym słowem ewentualnie jakoś dalej przetwarzać dane. To już wie tylko Adam :)

Ogolnie to bazy danych należy pchać tam gdzie jest uzasadnienie, no chyba ze ma sie skrzywienie zawodowe jak ja :) to sie wszystko trzyma w bazie danych :D

Odnośnik do komentarza
Udostępnij na innych stronach

Kombinowałem mniej więcej w tą samą stronę.

Dzięki za potwierdzenie i rozpisanie ;)

Wiecie chyba jak to czasem jest. Potrzebujecie coś zrobić,

rozpisujecie algorytm robaczkami na A3, kodujecie 2 dni,

a potem ktoś na to patrzy i pyta "a czemu nie użyłeś

komendy chrumkchrumk? Przecież to 100x szybsze

i mniej pisania.. ;)

Jak będę miał listę słów to już sobie poradzę. Nie ważny format.

Jest jakiś logiczny limit ilości wierszy w tabeli powyżej której

serwer zamieli się na śmierć? ;)

(nowożytna maszyna, kilka GB ramu)

Zjazdowe rozmowy zainspirowały mnie do upgrejdnięcia

kilku moich spa.. znaczy się rozbudowanych stron do testowania

obciążenia serwera ;)

Jestem w potrzebie - sprzedaje
cenne domeny regionalne za ułamek wartości
tylko do końca tyg. < link do ogłoszenia >

Odnośnik do komentarza
Udostępnij na innych stronach

200 MB = 200.000.000B

20% to spacje interpunkcja znaki końca linii

zostaje 160 MB= 160.000.000B

średnio słowo niech ma ok 8 znaków

mamy 20.000.000 słów do sprawdzenia

W przypadku gdy nie bedziemy się posilkować zadnym indeksem wraz ze wzrostem ilości danych bedzie nam to coraz wolniej szło sprawdzanie. Po sprawdzeniu np. tysiąca słów dodane następnego słowa to sprawdzenie liniowe czy już słowo istnieje. Jak dla mnie to bedzie problem NxN

W przypadku bazy danych i odpowiednich indeksów powinno być szybciej bo baza danych nie szuka liniowo tylko za pomocą np. drzewa

wyciągnięcie po indeksie z bazy 20.000.000 rekordów powinno być poniżej 1 ms

Licząc np. 10 ms na jedno słowo ( select insert update) całość powinna sie wykonac ok 200.000s czyli jakies 55 h ;)

Co do zasobów to dużo nie potrzeba:

baza bedzie miała jakieś 100 - 500 MB w zalezności od tego jak bogaty jezyk ma Twoj tekst

Pomyślał bym też nad wątkami , może dało by to jakiegos małego kopa.

Odnośnik do komentarza
Udostępnij na innych stronach

najważniejsze, to co już wspomniałeś, zależy od tego, co czego jest to potrzebne, jak duża ilość nowych słów (zdań) będzie dodawana, itd..

na początku, na tej bazie co mamy, znacznie szybciej będzie jak będziemy robić w ten sposób co podałem, czyli dodawać do osobnej tabeli kolejne słówka bez sprawdzania czy są już takie w tej tabeli (czyli w praktyce wyjdzie, że mamy tysiące takich samych słówek) a dopiero na końcu je policzyć/pogrupować z pomocą zapytania sql,

wyniki jakie otrzymamy można zapisać, i później:

1. jeżeli dodawanych jest niewiele nowych słówek to można sprawdzać czy jest takie w tabeli i robić update +1,

2. jeżeli bardzo dużo to policzyć jeszcze raz wszystko...

trudno mi powiedzieć na sucho ile to będzie czasu zajmowało ale samo grupowanie przy milionie rekordów myślę, że do dwóch minut (pole varchar, z indeksem),

select zadania, podział na słówka, insert zapewne kilkanaście minut...,

myślę, że te 200mb można do pół godziny obrobić... nie zdziwiłbym się jak o wiele szybciej...

Odnośnik do komentarza
Udostępnij na innych stronach

Wystarczy do tabeli wrzucić wszystkie słowa (bez usuwania duplikatów), potem posortować rosnąco / malejąco i zapisać na dysk, na koniec pliku dopisujemy coś co nie ma prawa wystąpić, np. $$%$#@11872

W php tworzymy tablicę 100 elementową $top=array(); $top['ilosc'] = array(); $top['slowo'] = array();

Teraz w pętli przerabiamy taki plik linijka po linijce:

jeśli dane słowo jest takie samo jak poprzednie: zwiększamy licznik $c++

jeśli słowo się różni: wyszukujemy najniższą wartość w tablicy $top['ilosc'], jeśli jest mniejsza od $c nadpisujemy nowym słowem i częstością występowania. ustawiamy $c na 0.

Najlepiej zapisywać najniższą wartość $top['ilosc'] w zmiennej, tak, żeby przetwarzać $top['ilosc'] tylko wtedy, kiedy trzeba, na początku $minimum = 0, jeśli słowo się różni, przetwarzamy tylko jeśli $c>$minimum, po operacji przetwarzania mamy nowe minimum $minimum = $c.

Jeśli tak to napisać, to cały algorytm w PHP ma złożoność liniową. Trochę się zdegeneruje, jeśli każde następne słowo będzie występowało w bazie o 1x więcej niż poprzednie, ale w praktyce to raczej niemożliwe.

Taki algorytm łatwo zrównoleglić: wystarczy np. podzielić słowa na kategorie wg. litery początkowej, gdzie każda kategoria = ilość_iter_ alfabecie/ilość_rdzeni. Mamy wtedy ilość_rdzeni plików wejściowych i każdy przetwarzamy tym algorytmem, na koniec łączymy wyniki.

Odnośnik do komentarza
Udostępnij na innych stronach

Może się komuś przyda...

Skrypcik przeglądający zdania z tabeli jeden i zapisujący słowa z tych zdań jako pojedyncze rekordy w tabeli 2.

Zrobiłem na szybko, metodą Voodoo. Perla nie znam ani trochę. U mnie działa :(

Odpala się z linii poleceń z parametrem - nazwą tabeli.

Mieli 10MB zdań na minutę (Athlon 3200).

edit: policzenie najczęściej występujących słów zapytaniem sql to 40min / 20mln rekordów

#!/usr/bin/perl
use DBI;
use CGI;
use utf8;
$c = new CGI;
$driver = "mysql";
$database="nazwa_bazy";
$hostname="127.0.0.1";
$port="3306";
$user="nazwa_usera";
$password="haslo_bazy";
$dsn = "DBI:$driver:database=$database;host=$hostname;port=$port";

my $dbh = DBI->connect($dsn, $user, $password);
$dbh->{mysql_enable_utf8};
my $sth = $dbh->prepare("SET NAMES 'utf8'");
$sth->execute();
my $sth = $dbh->prepare("SELECT * FROM $ARGV[0]");
$sth->execute();

while (my $ref = $sth->fetchrow_hashref())
{
$zdanie =  $ref->{'zdanie'};
#zamiana na małe litery
$zdanie =~ tr/A-Z/a-z/;

my @slowa = split (/ /, $zdanie);

foreach (@slowa) {
	#wywalamy znaki specjalne
	$_ =~ tr/.!,'"] //d;
	#tylko slowa dluzsze niz 5 znaków
	if (length($_)>5){
			$wstaw = "INSERT INTO s(s) VALUES (\"" . $_ . "\")";
			my $sth2 = $dbh->prepare("$wstaw");
			$sth2->execute();
			}
	}

}
$sth->finish();
$dbh->disconnect();

Jestem w potrzebie - sprzedaje
cenne domeny regionalne za ułamek wartości
tylko do końca tyg. < link do ogłoszenia >

Odnośnik do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Umieściliśmy na Twoim urządzeniu pliki cookie, aby pomóc Ci usprawnić przeglądanie strony. Możesz dostosować ustawienia plików cookie, w przeciwnym wypadku zakładamy, że wyrażasz na to zgodę. Warunki użytkowania Polityka prywatności