import re import numpy as np LEAD_PREP = ['qua', 'trong', 'do', 'bằng', 'từ', 'nhìn', 'với', 'theo', 'nhờ', 'vì', 'tại', 'để', 'khi', 'nếu', 'chính vì', 'thông qua'] FUNC_WORDS = ['là', 'thì', 'mà', 'nên', 'đã', 'sẽ', 'đang', 'của', 'cho', 'với', 'bởi', 'được', 'bị', 'những', 'các', 'rằng'] CAUSE = re.compile('^\\W*(do|vì|tại|bởi|nhờ|chính vì|nếu|tuy|mặc dù|khi)\\b.*\\b(nên|thì|mà)\\b', re.I) def first_words(s, n): w = re.findall(r'\w+', s.lower()) return ' '.join(w[:n]) def feats(s): s = ' '.join(s.split()) low = s.lower() toks = re.findall(r'\w+', low) n = max(len(toks), 1) f = {} f['log_len'] = np.log1p(n) f['ellipsis'] = float('...' in s or '…' in s) for p in ['qua', 'trong', 'do', 'bằng', 'từ', 'nhìn', 'với', 'theo', 'nhờ', 'vì', 'tại', 'để', 'khi', 'nếu']: f['lead_' + p] = float(first_words(s, 1) == p) f['lead_prep_any'] = float(any(first_words(s, len(p.split())) == p for p in LEAD_PREP)) f['cause_pair'] = float(bool(CAUSE.search(s))) f['n_comma'] = s.count(',') / n * 10 f['n_semicolon'] = s.count(';') f['n_colon'] = s.count(':') f['n_dash'] = len(re.findall(r'\s[-–—]\s', s)) f['n_paren'] = s.count('(') f['n_quote'] = s.count('“') + s.count('”') + s.count('"') + s.count('‘') + s.count('’') f['quote_unbal'] = float(s.count('“') != s.count('”') or s.count('"') % 2 == 1) f['n_sent'] = len(re.findall(r'[.!?]\s+[A-ZĐÀ-Ỹ]', s)) f['no_end_punct'] = float(not re.search(r'[.!?…”"]\s*$', s)) f['has_digit'] = float(bool(re.search(r'\d', s))) caps = re.findall(r'\b[A-ZĐ][\wÀ-ỹ]*', s) f['cap_ratio'] = len(caps) / n f['acronym'] = float(bool(re.search(r'\b[A-ZĐ]{2,}\b', s))) f['no_comma_long'] = float(',' not in s and n > 20) for w in FUNC_WORDS: f['fw_' + w] = toks.count(w) / n * 10 return f