2019年12月19日 星期四

時間的自然語言理解


本篇設計一個Regular Expression的式子及Python程式,來理解使用者輸入的時間(不含日期),轉成標準的timestamp後,輸出給其它程式使用。
像這種時間、日期、數字等,有規則的字詞,用Regular Expression比利用機器學習還容易多,用機器學習還比較容易失敗。
下面的程式所用的Regular Expression式子有可能會接受錯誤的時間表示方式,畢竟想把所有可能的表示法塞在同一個式子,本來就不太可能,故若要改善,需要拆成多個式子來處理。
程式最下面的MAIN區塊,queryString是輸入的時間有關字句,getTime() 會把標準時間傳回來。
import re import urllib import pandas as pd # constants for chinese_to_arabic CN_NUM = { '〇' : 0, '一' : 1, '二' : 2, '三' : 3, '四' : 4, '五' : 5, '六' : 6, '七' : 7, '八' : 8, '九' : 9, '零' : 0, '壹' : 1, '贰' : 2, '叁' : 3, '肆' : 4, '伍' : 5, '陆' : 6, '柒' : 7, '捌' : 8, '玖' : 9, '貮' : 2, '两' : 2, '0' : 0, '1' : 1, '2' : 2, '3' : 3, '4' : 4, '5' : 5, '6' : 6, '7' : 7, '8' : 8, '9' : 9 } CN_UNIT = { '十' : 10, '拾' : 10, '百' : 100, '佰' : 100, '千' : 1000, '仟' : 1000, '万' : 10000, '萬' : 10000, '亿' : 100000000, '億' : 100000000, '兆' : 1000000000000, } def chinese_to_arabic(cn): unit = 0 # current ldig = [] # digest for cndig in reversed(cn): if cndig in CN_UNIT: unit = CN_UNIT.get(cndig) if unit == 10000 or unit == 100000000: ldig.append(unit) unit = 1 else: dig = CN_NUM.get(cndig) if unit: dig *= unit unit = 0 ldig.append(dig) if unit == 10: ldig.append(10) val, tmp = 0, 0 for x in reversed(ldig): if x == 10000 or x == 100000000: val += tmp * x tmp = 0 else: tmp += x val += tmp return val def word2timestamp(test_str): regex = r"(上午|下午|凌晨|中午|今夜|傍晚|午夜|半夜|夜間|大清早|早上|早晨|晚|晚上)?([零一二兩三四五六七八九十0123456789]+)[點|時|:]([零一二兩三四五六七八九十0123456789]*)[分|:]?([零一二兩三四五六七八九十0123456789]*)秒?\s?(am|pm|a.m|p.m|AM|PM|A.M|P.M)?" match = re.search(regex, test_str, re.MULTILINE) l = [] l.append(chinese_to_arabic(match.group(2))) if (len(match.groups()) > 2): l.append(chinese_to_arabic(match.group(3))) if (len(match.groups()) > 3): l.append(chinese_to_arabic(match.group(4))) match.group(4) if ((match.group(1) == "下午") & (l[0] <= 11) & (l[0] >= 1)): l[0] += 12 if ((match.group(1) == "半夜") & (l[0] in [8, 9, 10, 11, 12])): l[0] += 12 if ((match.group(1) == "今夜") & (l[0] in [5, 6, 7, 8, 9, 10, 11, 12])): l[0] += 12 if ((match.group(1) == "傍晚") & (l[0] in [5, 6, 7, 8, 9, 10, 11, 12])): l[0] += 12 if ((match.group(1) == "午夜") & (l[0] in [5, 6, 7, 8, 9, 10, 11, 12])): l[0] += 12 if ((match.group(1) == "中午") & (l[0] in [1, 2, 3, 4, 5, 6])): l[0] += 12 if ((match.group(1) == "夜間") & (l[0] in [6, 7, 8, 9, 10, 11, 12])): l[0] += 12 if ((match.group(1) == "晚") & (l[0] in [6, 7, 8, 9, 10, 11, 12])): l[0] += 12 if ((match.group(1) == "晚上") & (l[0] in [6, 7, 8, 9, 10, 11, 12])): l[0] += 12 if l[0] == 24: l[0] = 0 string = l[0] for i in range(1, len(l)): string = "%s:%d" % (string, l[i]) return string def getTime(queryString): url = 'http://morpheus.itri-nlp.tw:9801/v2/nlu/predict?' + urllib.parse.urlencode({'q': queryString}) f = urllib.request.urlopen(url) timeInfo = pd.read_json(f.read()) return word2timestamp(timeInfo['response']['labels']['時間'][0]['rawEntity']) if __name__ == '__main__': queryString = '晚7點四十五分十二秒出發' print(getTime(queryString)) # OUTPUT "19:45:12"


















沒有留言:

張貼留言

IKEA吊櫃廚櫃

 好不容易裝好IKEA買來的吊櫃,花了三天。 從組裝,鑽牆,上牆調水平,累死我了。