文章目录
前言
本文基于代码分类功能开发记录进行了一些优化
1、将分类类别增加至15个类别
2、加入每种语言的keywords表
3、在计算句向量时,加入keywords权重
一、优化思路
上一版模型测试结果:1、在长文本测试集准确率达98%
2、在真实业务测试集准确率为49%
造成该结果可能的原因:
1、训练数据与真实业务数据相差较大:训练数据为一个完整的代码文件,而业务测试数据为代码段。
2、句向量计算不合理,不能体现每种语言的独特性:先前计算句向量时,用平均词向量代替句向量
二、所做的尝试
1.加入keywords权重计算句向量
在计算句向量时,还是只用平均词向量的计算方式,但加入了keywords的权重,分类模型为xgboost代码如下:
def wam(sentence, w2v_model):
arr = []
for s in str(sentence).split():
if s not in w2v_model.wv.vocab.keys():
arr.append(np.random.randn(1, 300))
else:
if s in keywords_result:
arr.append(w2v_model.wv.get_vector(s) * 5)
else:
arr.append(w2v_model.wv.get_vector(s))
return np.mean(np.array(arr), axis=0).reshape(1, -1)
两倍权重时:在业务数据上测试,准确率为63%
五倍权重时:在业务数据上测试,准确率为67%
2.更改词向量计算方式
词向量计算出来的向量,可以得到: 国王 + 女 = 女王
但代码之间,并不需要该关系(有点模糊,可以理解为代码与代码之间没有 for + if = XXX的关系),用词向量来将代码转为向量的方式并不合适,于是更改为tfidf的方式,分类模型为xgboost代码如下:
from sklearn.feature_extraction.text import TfidfVectorizer
def prepare_dataset(dataset_path):
"""Load data files from directory, split into train and test.
Return lists of target names, training samples, testing samples,
training targets and testing targets. """
# dataset_path = get_sgd_data_path()
dataset = load_files(dataset_path, load_content=True,
encoding='UTF-8', decode_error='replace')
X_train, X_test, y_train, y_test = train_test_split(
dataset.data, dataset.target, test_size=0.20, random_state=3114795823)
return dataset.target_names, X_train, X_test, y_train, y_test
dataset_path = '/Downloads/data'
target_names, X_train, X_test, y_train, y_test = prepare_dataset(dataset_path)
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(X_train)
在业务数据集上测试准确率为66%
3.加入keywords
还是使用tfidf+xgboost,但在每种语言训练文件夹下加入了对应的keywords.md文件。如图所示:
在业务数据集上测试准确率为67%
4.更改分类模型
向量化依旧使用tfidf,分类模型使用sgd,代码如下:
def prepare_pipeline(self):
""" Check to see if pipeline can be loaded from pickle. If not, train
pipeline. Return pipeline and list of target names."""
model_path = get_sgd_model_path()
target_names_path = get_sgd_model_target_names_path()
if os.path.isfile(model_path):
keystone = joblib.load(model_path)
target_names = joblib.load(target_names_path)
else:
target_names, X_train, X_test, y_train, y_test = self.prepare_dataset()
keystone = Pipeline([
('vectorizer', CountVectorizer(
stop_words='english',
# analyzer='char_wb',
# max_features=256,
)),
('tfidf', TfidfTransformer()),
('classifier', linear_model.SGDClassifier(
class_weight='balanced'
)) # 默认 SVM
])
keystone.fit(X_train, y_train)
joblib.dump(keystone, model_path, compress=1)
joblib.dump(target_names, target_names_path, compress=1)
return keystone, target_names
在业务数据集上测试准确率为84%
5.仅使用keywords,不使用模型
由于每种语言都有一些独特的关键词,于是尝试计算代码中每种语言keywords的个数,数量最大的特征keywords对应的语言即为预测的代码类型,代码如下:
pathlists = [c_keywords_path, cpp_keywords_path, go_keywords_path, java_keywords_path,\
lua_keywords_path, js_keywords_path, html5_keywords_path, php_keywords_path,\
python_keywords_path, rust_keywords_path, swift_keywords_path ]
plmapings = {'c': 0 , 'cpp': 1, 'golang': 2, 'java':3, 'lua': 4, 'javascript':5, 'html':6, 'php':7, 'python':8, 'rust':9, 'swift':10}
def get_pl_keywords(filepath):
key_words = []
with open(filepath, 'r', encoding='utf-8') as f:
key = f.read()
for i in key.split('\n'):
key_words.append(i)
return key_words
def count_keywords_num(text, keywords):
count = 0
data = text.split()
for word in keywords:
for i in data :
if word in i:
count += 1
return count
def count_all_pl_keywords_num(keywords_pathlists, text):
all_pl_keywords_num = []
for keypath in keywords_pathlists:
key_words = get_pl_keywords(keypath)
count = count_keywords_num(text, key_words)
all_pl_keywords_num.append(count)
return all_pl_keywords_num
def get_pl_type(pathlists, testdata, plmaping):
pl_keywords_num = count_all_pl_keywords_num(pathlists, testdata)
pl_index = pl_keywords_num.index(max(pl_keywords_num, key = abs))
result = list(plmaping.keys())[list(plmaping.values()).index(pl_index)]
return result
#%%
pl_type = get_pl_type(pathlists, testdata_result, plmapings)
在业务测试集上准确率为67%
后续优化
后续会整理出每种语言的常用包及常用库,加入到keywords中,对准确率应该会有进一步的提升
总结
1、从上面所做的5种测试可以发现,tfidf+keywords+sgd的效果最好,但我一直很不理解,为什么tfidf+keywords+xgboost会不如tfidf+keywords+sgd,如果有理解的话,可以指点一下,万分感谢
2、仅仅使用keywords的效果比使用模型的效果更好,由此可见,对数据的理解也是NLP开发非常重要的一部分。