Python机器学习项目的模板
1.定义问题
a)导入类库
b)导入数据集
from sklearn.datasets import load_files from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.naive_bayes import MultinomialNB from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import classification_report from sklearn.metrics import accuracy_score from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold from sklearn.model_selection import GridSearchCV from sklearn.ensemble import AdaBoostClassifier from sklearn.ensemble import RandomForestClassifier from matplotlib import pyplot as plt #导入数据 categories = ['alt.atheism','rec.sport.hockey','comp.graphics','sci.crypt', 'comp.os.ms-windows.misc','sci.electronics','comp.sys.ibm.pc.hardware', 'sci.med','comp.sys.mac.hardware','sci.space','comp.windows.x','soc.religion.christian', 'misc.forsale','talk.politics.guns','rec.autos','talk.politics.guns','rec.autos', 'talk.politics.mideast','rec.motorcycles','talk.politics.misc','rec.sport.baseball', 'talk.religion.misc' ] #导入训练数据 train_path = '/home/hadoop/DataSet/20news-bydate/20news-bydate-train' dataset_train = load_files(container_path=train_path,categories=categories) #导入评估数据 test_path = '/home/hadoop/DataSet/20news-bydate/20news-bydate-test' dataset_test = load_files(container_path=test_path,categories=categories)
利用机器学习对文本进行分类,与对数值特征进行分类最大的区别是:对文本进行分类时要先提取文本特征,相对于之前的项目来说,会有超过万个的特征属性,甚至会超过10万个。
2.文本特征提取
文本特征属于非结构化的数据,一般要转换成结构化的数据才能通过机器学习算法进行文本分类。常见的做法是将文本转换成“文档-词项矩阵”,矩阵中的元素可以使用词频或TF-IDF值等。
TF-IDF值是一种用于信息检索或数据挖掘的常用加权技术。TF的意思是词频,IDF的意思是逆向文件频率。TF-IDF的主要思想是:如果某一个词或短语在一篇文章中出现的频率高,并且在其他文章中很少出现,则认为此词或短语具有很好的类别区分能力,适合用于分类。TF-IDF实际上是TF*IDF。IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其他类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值小,则说明该词条t的类别区分能力不强。TF指的是某一个给定词的词语在该文件中出现的频率,这是对词数的归一化,以防止它偏向长的文件。IDF是一个词语普遍重要性的度量,某一个特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目,再将得到的商取对数得到。
#数据准备和理解 #计算词频 count_vect = CountVectorizer(stop_words='english',decode_error='ignore') X_train_counts = count_vect.fit_transform(dataset_train.data) #查看数据维度 print(X_train_counts.shape)
#计算TF-IDF tf_transformer = TfidfVectorizer(stop_words='english',decode_error='ignore') X_train_counts_tf = tf_transformer.fit_transform(dataset_train.data) #查看数据维度 print(X_train_counts_tf.shape)
这里通过两种方法进行了文本特征的提取,并且查看了数据维度,得到的数据维度还是非常巨大的。在后续的项目中,将使用TF-IDF进行分类模型的训练。因为TF-IDF的数据维度巨大,并且自用提取的特征数据,进一步对数据进行分析的意义不大,因此只简单地查看数据维度的信息。
3.评估算法
#设置评估算法的基准 num_folds = 10 seed = 7 scoring = 'accuracy'
线性算法:LR(逻辑回归)
非线性算法:CART,SVM,朴素贝叶斯,KNN
#评估算法 #生成算法模型 models = {} models['LR'] = LogisticRegression() models['SVM'] = SVC() models['CART'] = DecisionTreeClassifier() models['MNB'] = MultinomialNB() models['KNN'] = KNeighborsClassifier()
#比较算法 results = [] for key in models: kfold = KFold(n_splits=num_folds,random_state=seed) cv_results = cross_val_score(models[key],X_train_counts_tf,dataset_train.target,cv=kfold,scoring=scoring) results.append(cv_results) print('%s:%f(%f)'%(key,cv_results.mean(),cv_results.std()))
#箱线图比较算法 fig = plt.figure() fig.suptitle('Algorithm Comparison') ax = fig.add_subplot(111) plt.boxplot(results) ax.set_xticklabels(models.keys()) plt.show()
算法调参
通过上面的分析发现,逻辑回归(LR)和朴素贝叶斯分类器(MNB)算法值得进一步优化。下面对这两个算法进行调参,进一步提高算法的准确度。
逻辑回归调参
在逻辑回归中的超参数是C。C是目标的约束函数,C值越小则正则化强度越大。对C进行调参,每次给C设定一定数量的值,如果临界值是最优参数,重复这个步骤,直到找到最优值。
#算法调参 #调参LR param_grid = {} param_grid['C'] = [0.1,5,13,15] model = LogisticRegression() kfold = KFold(n_splits=num_folds,random_state=seed) grid = GridSearchCV(estimator=model,param_grid=param_grid,scoring=scoring,cv=kfold) grid_result = grid.fit(X=X_train_counts_tf,y=dataset_train.target) print('最优:%s使用%s'%(grid_result.best_score_,grid_result.best_params_))
朴素贝叶斯分类器调参
朴素贝叶斯分类器有一个alpha参数,该参数是一个平滑参数,默认值为1.0。我们可以对这个参数进行调参,以提高算法的准确度。
#调参MNB param_grid = {} param_grid['alpha'] = [0.001,0.01,0.1,1.5] model = MultinomialNB() kfold = KFold(n_splits=num_folds,random_state=seed) grid = GridSearchCV(estimator=model,param_grid=param_grid,scoring=scoring,cv=kfold) grid_result = grid.fit(X=X_train_counts_tf,y=dataset_train.target) print('最优:%s使用%s'%(grid_result.best_score_,grid_result.best_params_))
集成算法
除了调参,提高算法准确度的方法是使用集成算法。下面对两种集成算法进行比较,看看能否进一步提高模型的准确度。
1.随机森林
2.AdaBoost
#集成算法 ensembles = {} ensembles['RF'] = RandomForestClassifier() ensembles['AB'] = AdaBoostClassifier() #比较集成算法 results = [] for key in ensembles: kfold = KFold(n_splits=num_folds,random_state=seed) cv_results = cross_val_score(ensembles[key],X_train_counts_tf,dataset_train.target,cv=kfold,scoring=scoring) results.append(cv_results) print('%s:%f(%f)'%(key,cv_results.mean(),cv_results.std()))
集成算法调参
对随机森林算法进行优化,随机森林有一个重要的参数n_estimators,下面对n_estimators进行调参优化,争取找到最优解。
#调参RF param_grid = {} param_grid['n_estimators'] = [10,100,150,200] model = RandomForestClassifier() kfold = KFold(n_splits=num_folds,random_state=seed) grid = GridSearchCV(estimator=model,param_grid=param_grid,scoring=scoring,cv=kfold) grid_result = grid.fit(X=X_train_counts_tf,y=dataset_train.target) print('最优:%s使用%s'%(grid_result.best_score_,grid_result,best_params_))
确定最终模型
#生成模型 model = LogisticRegression(C=13) model.fit(X_train_counts_tf,dataset_train_target) X_test_counts = tf_transformer.transform(dataset_test.data) predictions = model.predict(X_test_counts) print(accuracy_score(dataset_test.target,predictions)) print(classification_report(dataset_test.target,predictions))