Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Скільки символів потрібно щоб написати вікіпедію?

with 4 comments

Не так важливо скільки там людей говоритиме українською коли настане технологічна сингулярність. Важлива сумарна обчислювальна потужність інтелекту що володіє українською. 😉 І взагалі варто опановувати хоч якісь основи навчання машин – це професія в якій роботи ще не скоро замінять людей. Щоб навчити машину мови – їй треба багааатезно прикладів. І найбільший шмат української мови який можна легко згодувати машині – вікіпедія. Тому сьогодні ми спробуємо з’ясувати що потрібно щоб отримати цей масив тексту, і порахувати на ньому якусь простеньку статистику, для якої не треба бази даних а вистачить оперативної пам’яті.

Перше що нам потрібно – копія бази даних вікіпедії. Тому що вікіпедія містить більше чверті мільйона статтей, і навіть якщо ми робитимемо по запиту на секунду, що вікіпедія не схвалює для всяких там приватних павуків, то складання індексу займе в нас (750000 сек)/ 3600 / 24 = 8.68 діб > тижня. Тому заходимо на
https://dumps.wikimedia.org/ , вибираємо дамп який більше подобається, наприклад останній дамп що містить статті (без сторінок обговорень) української вікіпедії і ставимо на скачування.

А поки воно скачується підготуємось його розпаковувати. Ми скачуємо заархівований XML, який при розпаковуванні займає щось біля 5GB. Всередині є багато тисяч елементів , кожен з яких містить деталі про сторінку. Ось код на Go який містить функцію Read що розархівовує і водночас парсить XML, та повертає канал в який кидає сторінку за сторінкою, а в головній функції ітерується по всіх сторінках і підраховує кількість символів в їх тексті. В кінці виводить статистику:


package main
import (
"fmt"
"log"
"os"
"sort"
)
type RuneFreq struct {
R rune
Freq uint
}
func main() {
if len(os.Args) < 2 {
log.Fatal("Please specify a file to read")
}
charcount := make(map[rune]uint)
count := 0
for page := range Read(os.Args[1]) {
count++
if count%123 == 0 {
fmt.Fprintf(os.Stderr, "\rPages: %d\t\tRunes: %d", count, len(charcount))
}
if page.Redirect != nil {
continue // skip redirects
}
for _, r := range []rune(page.Text) {
charcount[r]++
}
}
top := make([]RuneFreq, len(charcount))
i := 0
var sum uint = 0
for k, v := range charcount {
top[i] = RuneFreq{k, v}
i++
sum += v
}
sort.Slice(top, func(i, j int) bool {
return top[i].Freq < top[j].Freq
})
for i, rf := range top {
fmt.Println("%d) &#%d;: %d", len(charcount)-i, rf.R, rf.Freq)
}
fmt.Println("Total characters: %d", sum)
fmt.Println("Different characters: %d", len(charcount))
}

view raw

main.go

hosted with ❤ by GitHub


package main
import (
"compress/bzip2"
"encoding/xml"
"io"
"log"
"os"
"strings"
)
type Page struct {
Title string `xml:"title"`
Namespace int `xml:"ns"`
Id int `xml:"id"`
Text string `xml:"revision>text"`
Redirect *Redirect `xml:"redirect"`
}
type Redirect struct {
To string `xml:"title,attr"`
}
func (p Page) String() string {
redirect := ""
if p.Redirect != nil {
redirect = "-> " + p.Redirect.To
}
return p.Title + redirect + ": " + (p.Text + strings.Repeat(" ", 50))[:50]
}
func Read(filename string) <-chan Page {
out := make(chan Page, 100)
go func() {
f, err := os.Open(filename)
stopOnError(err)
decompressedFile := bzip2.NewReader(f)
xmlReader := xml.NewDecoder(decompressedFile)
for {
t, err := xmlReader.Token()
if err == io.EOF {
close(out)
break
}
stopOnError(err)
switch t := t.(type) {
case xml.StartElement:
if t.Name.Local == "page" {
var page Page
stopOnError(xmlReader.DecodeElement(&page, &t))
stopOnError(err)
out <- page
}
}
}
}()
return out
}
func stopOnError(err error) {
if err != nil {
log.Fatal(err)
}
}

Можна запускати його як go run main.go *.xml.bz2, а можна зробити go build і отримати скомпільований код, який вже запускати. Думаю за швидкістю вони співмірні.

Дізнаємось що українська вікіпедія станом на 3 березня (бо такий в мене дамп) складається з 4 138 529 133 символів, серед яких різних лише 24 190.

Різних символів не так вже й багато, для порівняння остання версія юнікоду має 136 755, але все одно забагато як на мене. Наприклад якщо захочеться скласти таблицю як часто який символ йде після даного (біграми), то в ній буде 585 156 100 клітинок. Це треба буде пару гігабайт оперативки аби порахувати лише диграми. Сторінок там приблизно 1 600 000 (а не 750 000), тому що крім статтей є ще шаблони, категорії, і тому подібні речі. Тому я думаю треба відкинути неважливі символи, наприклад взявши за поріг що символ має з’являтись у вікіпедії хоча б 16 000 разів (якщо менше, то шанс побачити його на випадково взятій сторінці менше 1%). А таких лише 229, і ось їхній номер в рейтингу, написання і кількість використань у вікіпедії:

229) 市: 17347
228) λ: 18004
227) ç: 18915
226) ε: 19037
225) č: 19328
224) ​: 19388
223) ñ: 19431
222) ل: 19786
221) ў: 20711
220) @: 21351
219) ą: 21381
218) É: 22425
217) ś: 22544
216) š: 22885
215) ′: 23578
214) ș: 23592
213) ρ: 23834
212) ±: 24008
211) ς: 24200
210) τ: 24465
209) ι: 25389
208) à: 25608
207) ę: 25616
206) ν: 25716
205) ń: 25991
204) ”: 29662
203) ا: 32288
202) ο: 35475
201) ‎: 36211
200) „: 38162
199) →: 38323
198) í: 40358
197) ş: 42223
196) α: 43669
195) †: 45094
194) Ь: 46660
193) è: 50851
192) ö: 50927
191) “: 51455
190) ä: 51800
189) −: 52985
188) $: 55963
187) ё: 55973
186) ²: 58338
185) ţ: 60505
184) ×: 61094
183) ă: 63880
182) ъ: 64358
181) á: 65593
180) ^: 68237
179) ł: 69450
178) Э: 69917
177) Ї: 72349
176) ü: 74505
175) â: 86866
174) ½: 92706
173) э: 97009
172) …: 98257
171) ~: 104201
170) ó: 113417
169) °: 138459
168) Щ: 144944
167) Ґ: 153541
166) ·: 170010
165) ’: 172548
164) é: 308459
163) №: 308648
162) И: 309865
161) Й: 333321
160) •: 349671
159) \: 352804
158) ґ: 364613
157) ́: 389166
156) Z: 408490
155) +: 522576
154)  : 555014
153) Ю: 573682
152) q: 574906
151) ы: 604142
150) : 630305
149) Ж: 690154
148) Y: 723229
147) X: 749583
146) Є: 765597
145) Q: 818419
144) Я: 930365
143) –: 942145
142) J: 961000
141) ?: 1046419
140) Ц: 1098377
139) W: 1185842
138) Е: 1540741
137) O: 1628778
136) Х: 1696070
135) Ш: 1724585
134) K: 1802117
133) V: 1805294
132) H: 1816527
131) Ч: 1855640
130) j: 1864115
129) z: 2061416
128) U: 2194056
127) G: 2744752
126) N: 2852071
125) M: 3061885
124) #: 3154223
123) L: 3181356
122) !: 3189165
121) B: 3369071
120) З: 3437745
119) x: 3452972
118) F: 3520991
117) T: 3583564
116) %: 3642707
115) І: 3655626
114) P: 3725526
113) E: 3972385
112) »: 3977385
111) «: 3980397
110) Ф: 4202078
109) I: 4388726
108) R: 4396989
107) У: 4451260
106) О: 4554868
105) Б: 4662681
104) C: 4700683
103) щ: 4747530
102) Т: 4828013
101) Р: 5285196
100) Д: 5297868
99) A: 5304565
98) Н: 5308271
97) D: 5412754
96) Л: 5463510
95) v: 5601059
94) S: 5771420
93) —: 5876110
92) Г: 6196594
91) *: 6308184
90) _: 6536077
89) М: 6714179
88) є: 6725025
87) k: 6994569
86) &: 7431439
85) А: 8011695
84) В: 8034456
83) ф: 8301528
82) y: 8544168
81) ;: 9651561
80) С: 9778231
79) 7: 9836255
78) ш: 10032005
77) ю: 10424706
76) П: 10504497
75) w: 10609713
74) (: 10822363
73) ): 10861049
72) 6: 10922925
71) К: 11311101
70) 8: 11392131
69) “: 11480435
68) 4: 11994852
67) 5: 12855281
66) 3: 13149018
65) ж: 13461373
64) >: 14339625
63) <: 14353972
62) ї: 14915551
61) h: 15043805
60) m: 15056183
59) х: 16421470
58) f: 16484180
57) u: 17314042
56) g: 17753361
55) b: 18992562
54) 9: 19917121
53) :: 20761022
52) ц: 21063193
51) ч: 21089655
50) d: 21132407
49) p: 22184976
48) /: 22493164
47) c: 22688474
46) {: 23253440
45) }: 23256779
44) ,: 24259060
43) 2: 25895208
42) б: 27028220
41) ': 27719818
40) -: 29433960
39) й: 29504263
38) г: 32647216
37) з: 34131397
36) 0: 34211416
35) l: 35713324
34) .: 36224151
33) s: 36570492
32) o: 36864174
31) 1: 37256409
30) ь: 37873838
29) i: 37914159
28) я: 40403600
27) n: 41935115
26) r: 43452098
25) п: 45627724
24) a: 47339118
23) t: 49644507
22) м: 51192263
21) =: 52585455
20) д: 54742090
19) у: 56282864
18) e: 60511715
17)
: 68855138
16) к: 77929326
15) л: 78327225
14) [: 81918527
13) ]: 81923177
12) с: 85389668
11) в: 88260931
10) |: 90345542
9) т: 99966314
8) е: 100782938
7) и: 110643874
6) р: 118651169
5) і: 130028472
4) н: 154575149
3) о: 178231842
2) а: 180553597
1) : 506900824

Цих 229 символів використовуються сумарно 4 136 342 085 разів, а це складає 99.95% всіх символів вікіпедії. Тому рештою думаю дійсно можна знехтувати.

Written by bunyk

16 Березня, 2018 at 23:30

Опубліковано в Кодерство, Павутина

Tagged with ,

Відповідей: 4

Subscribe to comments with RSS.

  1. А чому } більше ніж { ? Те саме про [ ]

    Daniel Hlynskyj

    20 Березня, 2018 at 21:27

  2. […] відтоді як я рахував символи вікіпедії пройшло вже більше року. Рахував я їх за допомогою Go, хоча можна було сильно […]


Залишити коментар

Цей сайт використовує Akismet для зменшення спаму. Дізнайтеся, як обробляються ваші дані коментарів.