Kategorizace firem podle klíčových slov
projekt byl zpracován v rámci Digitální akademie Czechitas - datová analytika - podzim 2019
Na projektu pracovaly: Lucie Daniela (Inka) Dvořáková a Magdalena Hudcová
Mentor projektu: Martin Zelený
Používané nástroje: python, MySQL, MongoDB, KNIME,
Kódy, které jsme použily pro náš výsledný projekt jsou uloženy v repozitáři Github na adrese https://github.com/Rukkam/projekt/tree/master
Popis tématu:
Na tomto projektu spolupracujeme s firmou D.H.O.
s.r.o., která provozuje portál EXPANZO. Jednou
z činností, kterou se firma zabývá je zakázkový prodej databází firem a
specializovaných oborových databází. K vyhledávání firem využívají předmět
činnosti uvedený v rejstříku firem a zařazení do kategorií dle CZ-NACE.
Firma však hledá optimálnější způsob třídění firem. Proto jsme se rozhodly, že
v našem projektu prozkoumáme možnosti kategorizace firem podle klíčových
slov uvedených v hlavičkách jejich webových stránek.
Od firmy jsme dostaly k dispozici databáze firem s
údaji z veřejných rejstříků (název, sídlo, právní forma, předmět činnosti…) a
hlavičky webů některých firem ve formátu BSON.
Získání klíčových slov
Ze souboru, který obsahoval hlavičky webů, jsme chtěly
získat pouze potřebné údaje, tedy firm_id a keywords. Soubor však byl ve
formátu BSON, se ani jedna z nás ještě nesetkala. Nainstalovaly jsme si
tedy NoSQL databázi Mongo DB, která formát BSON podporuje. Avšak ani
s touto databází jsme se ještě nikdy nesetkaly, proto jsme musely pochopit
její princip a naučit se v ní pracovat. Jako nejjednodušší způsob nám
přišlo exportovat data do formátu JSON a dále s nimi pracovat mimo tuto
databázi. Exportovaný soubor ale obsahoval znaky, které nám bránily s ním pracovat
jako s validním formátem JSON.
{
"_id" : ObjectId("5581a042d3b7fffc238c7d9a"),
"_ns" : "FirmDbWebKeywords",
"active" : NumberLong(1),
"date_added" : ISODate("2015-06-17T16:28:50.000+0000"),
"date_modified" : ISODate("2019-05-21T21:11:37.000+0000"),
"description" : {
"cs" : "jazykova skola olomouc, SZs a VOSz Olomouc, jazyková škola Olomouc,základní informace"
},
"firm_id" : NumberInt(13142),
"id" : NumberLong(5),
"keyword" : [
{
"id" : NumberInt(1424586),
"lang_id" : NumberInt(1),
"name" : "jazykovka olomouc"
},
Rozhodly jsme se tedy napsat skript preprocesoru v pythonu a s pomocí regulérních výrazů přebytečné znaky odstranit. Část kódu vypadala následovně:
{
"_id" : ObjectId("5581a042d3b7fffc238c7d9a"),
"_ns" : "FirmDbWebKeywords",
"active" : NumberLong(1),
"date_added" : ISODate("2015-06-17T16:28:50.000+0000"),
"date_modified" : ISODate("2019-05-21T21:11:37.000+0000"),
"description" : {
"cs" : "jazykova skola olomouc, SZs a VOSz Olomouc, jazyková škola Olomouc,základní informace"
},
"firm_id" : NumberInt(13142),
"id" : NumberLong(5),
"keyword" : [
{
"id" : NumberInt(1424586),
"lang_id" : NumberInt(1),
"name" : "jazykovka olomouc"
},
Rozhodly jsme se tedy napsat skript preprocesoru v pythonu a s pomocí regulérních výrazů přebytečné znaky odstranit. Část kódu vypadala následovně:
import re
patern=re.compile(r'.*ISODate\(("[\dT:.+-]+"\)).*')
with open("keywords_working.txt", encoding="utf-8") as soubor:
result = json_normalize(soubor)
print(result)
Nakonec jsme se rozhodly tento způsob nepoužít a propojit
Mongo DB s pythonem prostřednictvím knihovny pymongo:
import pymongo
import pprint
import re
myclient = pymongo.MongoClient()
mydb = myclient['daprojekt']
mycol = mydb["firm_db_web_keywords"]
print(mydb.list_collection_names())
i=1
with open("keyword_nove.txt", mode='w', encoding='utf-8')as f:
for x in mycol.find({},{"firm_id":1,"keyword":1}):
x=str(x)
f.write("{}\n".format(x))
pprint.pprint(x)
Výstupem byl textový soubor:
{'_id': ObjectId('55816b68d3b7ff9e0b8c7d9a'), 'firm_id': 11374, 'keyword': [{'id': 1, 'lang_id': 1, 'name': 'k2'}, {'id': 2, 'lang_id': 1, 'name': 'k3'}, {'id': 1424594, 'lang_id': 2, 'name': 'krčma'}, {'id': 1424595, 'lang_id': 2, 'name': 'na'}, {'id': 1424596, 'lang_id': 2, 'name': 'statku'}, {'id': 1424597, 'lang_id': 2, 'name': 'hospoda'}, {'id': 1424598, 'lang_id': 2, 'name': 'restaurace'}, {'id': 1424599, 'lang_id': 2, 'name': 'hostinec'}, {'id': 1424600, 'lang_id': 2, 'name': 'rodinná'}, {'id': 1424601, 'lang_id': 2, 'name': 'podniková'}, {'id': 1424602, 'lang_id': 2, 'name': 'oslava'}, {'id': 1424603, 'lang_id': 2, 'name': 'úpořiny'}, {'id': 1424604, 'lang_id': 2, 'name': 'bystřany'}, {'id': 1424605, 'lang_id': 2, 'name': 'teplice'}]}
{'_id': ObjectId('5581a037d3b7ff98018c7d9c'), 'firm_id': 172773, 'keyword': [{'id': 2473509, 'lang_id': 1, 'name': ''}]}
Po odstranění nepotřebných znaků jsme si mohly konečně pořádně prohlédnout klíčová slova a začít se slovy pracovat. Zjistily jsme ale, že spousta slov obsahuje špatnou diakritiku.
{'_id': ObjectId('5581a037d3b7ff98018c7d9c'), 'firm_id': 172773, 'keyword': [{'id': 2473509, 'lang_id': 1, 'name': ''}]}
Po odstranění nepotřebných znaků jsme si mohly konečně pořádně prohlédnout klíčová slova a začít se slovy pracovat. Zjistily jsme ale, že spousta slov obsahuje špatnou diakritiku.
Oprava chybné diakritiky
Začala jsem tedy pracovat na opravení diakritiky. Klíčová slova postahovaná z webů s různým kódováním. S pomocí knihovny chardet jsme v pythonu vytvořila skript, který má detekovat kódování. Detekování se však nepodařilo, klíčová slova byla pro detekci pravděpodobně malým vzorkem. S pomocí knihovny unicode jsem vytvořila skript, který měl dokázat opravit slova v kódování cp1250 do UTF-8, ale byla opravena jen část klíčových slov. Většina hlaviček webů obsahovalo údaje, v jakém kódování web je, ale ani dekódování podle těchto údajů se u mnoha slov nepodařilo. Firma nám tedy vyšla vstříc a stáhla hlavičky webů znovu. Tento soubor již obsahoval výrazně méně slov se špatnou diakritikou.
Nové stahování a čištění slov
Nový soubor bylo nutné opět vložit do databáze Mongo DB a s pomocí pythonu stáhnout potřebné údaje. Některá slova však stále obsahovala znaky a druhy slov, které by nám výsledek mohly zkreslit, proto bylo nutné je odstranit.
Python skript, který jsme použily zde
Tento proces více popisuje Inka ve svém blogu zde:
Jaká klíčová slova jsme při čištění musely smazat
nejčastěji?
Jaká klíčová slova se po vyčištění objevovala nejčastěji?
Lematizace slov:
Protože čeština je jazyk se spoustou různých tvarů slov,
bylo nutné vyčištěná slova lematizovat, tedy převést na základní tvary.
K tomu jsme využily morfologický analyzátor Majka. Unikátní slova jsme
prostřednictvím skriptu v pythonu zaslaly na API. Získaly jsme tak tabulku
unikátních klíčových slov a jejich lematizovaných podob. Podrobnější postup při
lematizaci slov najdete opět na blogu Inky zde
Skript v pythonu pro zasílání slov na lematizaci:
Skript v pythonu pro přípravu slov na lematizaci zde
Skript v pythonu pro zasílání slov zde
Clustering:
Nyní, když jsme již měly soubor obsahující ID firmy a
k ní patřící lematizovaná klíčová slova, jsme začali přemýšlet nad
členěním. Po zvážení všech možností procesu kategorizace firem jsme se rozhodly
pro strojové učení. Nevíme, jestli je to nejoptimálnější způsob, ale přišel nám
jako vhodný a zároveň jsme se s jeho metodami chtěly více seznámit.
Zatímco Inka zkoumala možnosti použití strojového učení v pythonu, já jsem
hledala další nástroje, které bychom mohly použít. A nalezla jsem!!! Komplexní
nástroj pro datové analýzy KNIME mě jako budoucí datovou analytičku ohromil. Po
zvážení jsme se s Inkou rozhodly pro clustering využít tento nástroj. Inka
připravila základní model
Vzhledem k rychlosti zpracování dat jsme se nakonec
rozhodly využít model využívající pro clustering fuzzy c-means:
Přesnější popis tohoto algoritmu má opět na svém blogu INKA zde
Výstupem Fuzzy c-means (kdy jsme předem zadaly požadavek na
rozdělení do 10 skupin) je tabulka s pravděpodobnostmi pro jednotlivé firmy a
clustery:
Vzhledem k obsáhlosti projektu a časové dotaci jsme
v této fázi musely projekt prozatím ukončily. Nyní by bylo potřeba udělat
podrobnou analýzu výsledků clusteringu a hledat nejvhodnější nastavení.
Naskýtá se nám však spousta dalších návrhů a otázek pro
další pokračování projektu:
-
Důležité je především ověřit, zda zařazení firem
do kategorií dává smysl a jestli odpovídá tomu, čemu se opravdu věnují.
-
Zjistit, jaký počet skupin je optimální
-
Porovnat výsledky naší kategorizace s již
existující kategorizací CZ -NACE
-
Bylo by vhodné podrobit dalšímu zkoumání také
klíčová slova a zjistit, zda opravdu odpovídají činnosti firmy. S tím souvisí
také možnost provedení textové analýzy celého webu.
Slepé uličky
Při zpracování projektu jsme se
dostávaly do spousty slepých uliček. Spousty skriptů, vizualizací apod.(tedy i
spousty hodin práce) jsme nakonec do výsledného projektu nezařadily. Ale i při
této práci jsme se naučily spoustu nového.
Co mi projekt dal
Práce na projektu byla vzhledem
k našim dosavadním znalostem a časovému omezení náročná, ale myslím, že
jsme splnily náš hlavní cíl. Prostřednictvím práce na projektu jsme chtěli
získat co nejvíce nových dovedností a zkušeností.
Zlepšila jsem se v práci s těmito nástroji:
Python, MySQL,KNIME, MongoDB, Power BI
Zjistila jsem, že samostudiem se
dokážu naučit pracovat s různými nástroji.
Při práci na projektu jsme také
zjistily limity našich počítačů 😉.
Velkým objevem byl komplexní
nástroj pro datovou analytiku KNIME, který mě velmi zaujal.
Při řešení problému byla důležitá
také spolupráce. Protože byl projekt obsáhlý, musely jsem se podílet na dílčích
úkolech, správně si dělit a plánovat práci a neustále vše společně konzultovat.
Což si myslím, že se nám podařilo a moc za to děkuji své partnerce Ince a také
našemu mentorovi Martinu Zelenému, který nás velmi podporoval. S poděkováním
nesmím zapomenout také na firmu D.H.O s.r.o., která nám poskytla data pro
zpracování.