自然语言处理--大作业

1.问题描述:比较三个分类器在影评分类任务上的性能,训练机1500,测试集500;朴素贝叶斯有三个常用模型:高斯、多项式、伯努利;KNN选择k(最好是交叉验证);SVM选择核函数。问题要求:对每个模型简述原理,说明每个参数调整的意义,简单概括3个分类器在影评分类上的性能。

2.综述如何使用ROC曲线和AUC评价一个二值分类器。

 


1.1原理:

  朴素贝叶斯模型:选择具有最高后验概率作为确定类别的指标。

  KNN模型:如果待测样本在特征空间中的k个最邻近样本中的大多数属于某一个类别,则该样本也属于这个类别,并拥有这个类别上样本的特征。实现确定近邻数,一般为奇数;根据事先确定的距离度量公式(欧式距离),计算待分类数据点和所有已分类样本点之间的距离,并计算出最近的k个样本点;统计哥哥样本点中,各个类别的数量,数量最多的样本类型,即为待分类数据的类型。当样本数量不平衡时,一个类的样本数量很大,而其他样本数量很少时,很有可能导致,当输入一个未知样本时,该样本的K个邻居中大数量类样本占多数;可以通过为距离设置权值来改进,与该样本距离大的权值小,与该样本距离小的权值大。

  SVM:支持向量机是一种回归和支持向量机算法,通过调节核函数参数的设置,可将数据集映射到多维平面上,对其细粒度化,从而使它的特征从二维变成多维,将在二维上线性不可分的问题转化为在多维上线性可分的问题,最后再寻找一个最优切割平面(相当于在决策树基础上再寻找一个最优解),因此svm的分类效果是优于大多数的机器学习分类方法的。

  线性核函数:主要用于线性可分的情况,我们可以看到特征空间到输入空间的维度是一样的,其参数少速度快,对于线性可分数据,其分类效果很理想,因此我们通常首先尝试用线性核函数来做分类,看看效果如何,如果不行再换别的。

  多项式核函数可以实现将低维的输入空间映射到高纬的特征空间,但是多项式核函数的参数多,当多项式的阶数比较高的时候,核矩阵的元素值将趋于无穷大或者无穷小,计算复杂度会大到无法计算。

  高斯径向基函数是一种局部性强的核函数,其可以将一个样本映射到一个更高维的空间内,该核函数是应用最广的一个,无论大样本还是小样本都有比较好的性能,而且其相对于多项式核函数参数要少,因此大多数情况下在不知道用什么核函数的时候,优先使用高斯核函数。

  采用sigmoid核函数,支持向量机实现的就是一种多层神经网络。

  在选择核函数时,吴恩达在课上提到过几种方法:  

  • 如果特征的数量大到和样本数量差不多,则选用LR或者线性核的SVM;
  • 如果特征的数量小,样本的数量正常,则选用SVM+高斯核函数;
  • 如果特征的数量小,而样本的数量很大,则需要手工添加一些特征从而变成第一种情况。 

 

1.2 比较三个算法在影评分类上的性能

1.2.1 SVM四个不同核函数的效果比较:

  

结果显示:SVM四个核函数中linear效果最好,ploy最差。

1.2.2 KNN的最佳k值

  要求使用交叉验证,选择kfold算法,K-folds算法是把数据分成k份,进行k此循环,每次不同的份分别来充当测试组数据。一般选择kfold=10.

对于训练集[:1500,,:],选择k在[1,40]之间。

结果显示:在k = 22 时验证的效果最好

1.2.3 朴素贝叶斯

结果显示:MultionmialNB模型效果最好,达到0.83

  

2.综述如何使用ROC曲线和AUC评价一个二值分类器。

ROC(Receiver Operating Characteristic,接受者工作特征曲线)曲线和AUC常被用来评价一个二值分类器(binary classifier)的优劣。

AUC是现在分类模型,特别是二分类模型使用的主要离线评测指标之一。相比于准确率、召回率、F1等指标,AUC有一个独特的优势,就是不关注具体得分,只关注排序结果,这使得它特别适用于排序问题的效果评估,例如推荐排序的评估。AUC这个指标有两种解释方法,一种是传统的“曲线下面积”解释,另一种是关于排序能力的解释。例如0.7的AUC,其含义可以大概理解为:给定一个正样本和一个负样本,在70%的情况下,模型对正样本的打分高于对负样本的打分。可以看出在这个解释下,我们关心的只有正负样本之间的分数高低,而具体的分值则无关紧要。

ROC曲线的横坐标为false positive rate(FPR),纵坐标为true positive rate(TPR)(也就是recall)。

 

 

 

 

 

ROC曲线有四个特殊点和一条线:

第一个点,(0,1),即FPR=0, TPR=1,这意味着FN(false negative)=0,并且FP(false positive)=0。Wow,这是一个完美的分类器,它将所有的样本都正确分类。

第二个点,(1,0),即FPR=1,TPR=0,类似地分析可以发现这是一个最糟糕的分类器,因为它成功避开了所有的正确答案。

第三个点,(0,0),即FPR=TPR=0,即FP(false positive)=TP(true positive)=0,可以发现该分类器预测所有的样本都为负样本(negative)。

第四个点(1,1),分类器实际上预测所有的样本都为正样本。经过以上的分析,我们可以断言,ROC曲线越接近左上角,该分类器的性能越好。

ROC曲线图中y=x上的点。这条对角线上的点其实表示的是一个采用随机猜测策略的分类器的结果(FP = TN, TP = FN,这样FP+TP = TN + FN,即Y = N,也就是随机猜测了),例如(0.5,0.5),表示该分类器随机对于一半的样本猜测其为正样本,另外一半的样本为负样本。经过以上的分析,我们可以断言,ROC曲线越接近左上角,该分类器的性能越好。

AUC(Area Under Curve)被定义为ROC曲线下的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。


 

3.分别在tf,tfidf词袋模型上比较三个分类器。

3.1 在tf词袋模型上的效果结果:

features = np.zeros([len(documents),len(word_features)],dtype=float)
for n in range(len(documents)):
        document_words = documents[n][0]
        pdf=collections.Counter( document_words)
        for  m in range(len(word_features)):
                if word_features[m] in document_words:
                        features[n,m] = pdf[word_features[m]]

SVM:

SVM

KNN:

朴素贝叶斯:

 

3.2 TF-IDF词袋模型上:

vectorizer=CountVectorizer(min_df=100,stop_words='english')#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频  
transformer=TfidfTransformer()#该类会统计每个词语的tf-idf权值
tfidf=transformer.fit_transform(vectorizer.fit_transform(documents_words))#fit_transform计算tf-idf,fit_transform将文本转为词频矩阵  
word=vectorizer.get_feature_names()#获取词袋模型中的所有词语  
features=tfidf.toarray()#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重
print(features.shape)

SVM:

from sklearn.svm import SVC
svmmodels =[]
svmmodels.append(("linear",SVC(kernel='linear')))
svmmodels.append(("poly",SVC(kernel='poly')))
svmmodels.append(("sigmoid",SVC(kernel='sigmoid')))
svmmodels.append(("rbf",SVC(kernel='rbf')))
for name,model in svmmodels:
        model.fit(train_set1,target_train)
        pred = model.predict(test_set1)
        print("{0}准确率为:{1}".format(name,sum([1 for n in range(len(target_test)) if pred[n]==target_test[n]])/len(target_test)))

from sklearn.svm import SVC
svclf = SVC(kernel ='linear',probability=True)
svclf.fit(train_set1, target_train)
pred_svc = svclf.predict(test_set1)
print('SVM=',sum(pred_svc==target_test)/len(target_test))

 

KNN:

#KNN
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score


result =[]
for k in range(1,40):
        kfold = KFold(n_splits=10)
        knnclf = KNeighborsClassifier(n_neighbors=k)  #通常默认为5
        cv_result = cross_val_score(knnclf,train_set1,target_train,cv=kfold)
        #print(sum([1 for n in range(len(target_test)) if pred[n]==target_test[n] ])/len(target_test))
        print("k = {0};cross_val_score:{1}\n".format(k,cv_result.mean()))
        result.append(cv_result.mean())

朴素贝叶斯:

 

#朴素贝叶斯
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import MultinomialNB
from sklearn.naive_bayes import BernoulliNB

nbmodels = []
nbmodels.append(("GaussianNB",GaussianNB()))
nbmodels.append(("MultinomialNB",MultinomialNB()))
nbmodels.append(("BernoulliNB",BernoulliNB()))

for name,model in nbmodels:
        model.fit(train_set1,target_train)
        pred = model.predict(test_set1)
        print("{0}模型的预测准去率:{1}".format(name,sum([1 for n in range(len(test_set1)) if pred[n] == target_test[n]]) / len(target_test)))

 

 3.3 结果总结:

 经过结果的对比,显示出 KNN 虽然在TF-IDF模型上的准确率明显高于TF模型,但是仍然弱于SVM和朴素贝叶斯模型;朴素贝叶斯分类器在两种模型上的效果差不多,甚至在TF-IDF上有减弱的趋势;SVM分类器得出的结果较为稳定。

 

posted @ 2018-05-01 13:54  Qamra  阅读(1965)  评论(0编辑  收藏  举报