1. 程式人生 > >文字內容分析和智慧反饋(2)- 資料預處理和按緯度統計

文字內容分析和智慧反饋(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展現看看呢?
這不是核心需求。而且想要使用這兩個工具達到生產級的要求,太麻煩。