文字內容分析和智慧反饋(2)- 資料預處理和按緯度統計
書接上文,考慮4個核心功能的實現,先考慮:資料預處理和按緯度統計。
1、資料預處理
1.1、基本原則
首先,考慮資料的格式。
業務資料是儲存在關係型資料庫中的。資料分析的部分,我們將使用Weka,雖然Weka習慣ARFF格式,為了實現資料分析和提取的自動化,我們將通過Weka的JDBC介面為其提供資料。這樣,可以使用ETL工具或者通過程式程式碼執行SQL實現資料提取和格式轉換。
在開發階段,我們基本上可以將資料提取和轉換邏輯固定下來,沒有必要採用專門的ETL工具。
其次,考慮資料轉換的要求。
我們初步確定的關鍵屬性為:業務板塊、行政區劃、時間段、文件編號、專家、 詞、 詞頻。對於空值需要設定合理的預設值。為了便於分析,需要將時間段等連續值進行離散化處理。
再其次,需要考慮資料的層級。
業務板塊和行政區劃都存在分級的情況。在初期,為了簡化問題,將行政區劃做扁平化處理,認為只有一個層級。但後續處理過程中,根據資料密度的不同,可能將本來同一個級別的資料,合併若干稀疏的行政區劃,對資料過密的區劃進行進一步的拆分。
對於業務板塊,本身是樹形結構,先按最細的粒度分析,稍後可以實現roll up和drill down的功能。時間段,也可以按不同粒度分析。
最後,考慮資料處理的策略和頻度。
由於資料條目中間不存在複雜關係,天然支援Map-Reduce處理架構,支援依據timestamp增量處理。
1.2、具體實現
1.2.1、 分析結果的格式
首先,定義儲存分詞結果的表。
create table doc_word_segmentation{
doc_id varchar2(32),
busi_sector varchar2(30),
busi_prop1 varchar2(100),
busi_prop2 varchar2(100),
busi_prop3 varchar2(100),
busi_prop4 varchar2(100),
busi_prop5 varchar2(100),
reg_org varchar2(9 ),
timespan varchar2(8),
inspector varchar2(32),
word varchar2(200),
cnt number(18,0)
}
這個表是中間過程表,保持了資料的最細粒度,可以通過word反查得到doc_id,從而可以回溯原始資料。
假設原資料有2000萬條,每天增加4000條,每條分詞得到50個詞。
那麼這個表將有10億條記錄,每天增加20萬條。
效率不太高,不能儲存所有的記錄。
如果只儲存當前半年的,那麼共3600萬條記錄,貌似可以接受了。
更極端的情況,這個表可以只用做儲存中間結果,彙總後即刪除掉臨時資料。
對於半年以前的資料,彙總後,只儲存彙總後的結果。
對上表彙總後得到:
create table doc_word_statistics{
word varchar2(200),
busi_sector varchar2(30),
busi_prop1 varchar2(100),
busi_prop2 varchar2(100),
busi_prop3 varchar2(100),
busi_prop4 varchar2(100),
busi_prop5 varchar2(100),
reg_org varchar2(9),
timespan varchar2(8),
inspector varchar2(32),
cnt number(18,0)
}
這個表的資料是我們真正需要的。
是後續工作的基礎。
1.2.2、 分詞演算法
可供選擇的中文分詞演算法很多。
暫時不考慮需要License的。
先試試je-analysis和IKAnalyzer。
找jar包,寫程式碼很簡單,不冗述。jar包可能存在和lucene相容的問題,不一定找最新的,先實現,以後再慢慢優化。
字典需要慢慢積累,需要自動給出建議,批量稽核入庫。
1.2.3、 程式碼實現
通過實現以下函式最終實現程式功能:
interface TextAnalyzer{
/**
* 返回分詞結果,Map的key為word,value為word在文件中出現的次數。
*/
Map<String,Long> wordSegmentat(String text);
/**
* 分析文件,得到分析結果資料。
* 可進一步彙總,或暫時先入庫儲存。
*/
List<DocWordSegmentationDomainObject> analyzeDoc(String docId);
/**
* 用於多worker協作執行大批量分析任務。
* timespan 可以是 201501 也可以是 20150520 ,甚至是 2015052001。
* 視資料量而定。
*/
void analyzeByTimespan(String timespan);
/**
* 對分詞結果進行彙總。
*/
void statistics(String timespan);
}
2、按緯度統計
基於資料預處理的結果,很容易通過SQL獲得按緯度統計的結果。
既然提到“緯度”了,要不要藉助Mondrian等工具定義一個Cube,通過jPilot展現看看呢?
這不是核心需求。而且想要使用這兩個工具達到生產級的要求,太麻煩。