基于SVM的图像二分类算法

本实验是用的python代码实现图像的二分类问题,我是在eclipse中搭建python环境。

一、数据集处理

我采用的是甜椒叶数据集(我忘了下载地址在哪里,我只用了一部分数据集),其中健康叶片有375张,病害叶片有313张,分别存放于两个文件夹中。如下图所示:

由于代码的原因,需要将文件夹的名称改为0和1,同时之后的处理会更加方便。0表示健康叶片,1表示病害叶片。

二、图片预处理

在进行图片预处理时,首先遍历整个数据集,将图片的大小重新设置为 256 x 256 的大小,然后进行直方图特征提取,文件夹的名字即为图片标签,分别将图片信息和 标签信息传入两个数组中,这两个数组再最后传入算法当中进行模型训练。具体代码及流程如下:

1、首先需要读入训练数据,同时重置图片大小,代码如下:

X = []
Y = []

for i in range(0, 2):
    #遍历文件夹,读取图片
    for f in os.listdir("G:/Download_Data_bishe/leaf_data/pepper_bellSmall/%s" % i):
        #打开一张图片并灰度化
        Images = cv2.imread("G:/Download_Data_bishe/leaf_data/pepper_bellSmall/%s/%s" % (i, f)) 
        image=cv2.resize(Images,(256,256),interpolation=cv2.INTER_CUBIC)
        hist = cv2.calcHist([image], [0,1], None, [256,256], [0.0,255.0,0.0,255.0]) 
        X.append(((hist/255).flatten()))
        Y.append(i)
X = np.array(X)
Y = np.array(Y)

2、调用自动调参函数GridSearchCV(网格搜索)对SVC()中的几个重要参数进行调参,注意,GridSearchCV函数要求的数据集很小,否则调参时间会很长,甚至调不出来,具体代码如下:

#自动调参函数
tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
                      'C': [1, 10, 100, 1000]},
                    {'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]
scores = ['precision', 'recall']
for score in scores:
    print("# Tuning hyper-parameters for %s" % score)
    print()
  
    # 调用 GridSearchCV,将 SVC(), tuned_parameters, cv=5, 还有 scoring 传递进去,
    clf = ms.GridSearchCV(svm.SVC(), tuned_parameters, cv=10,
                       scoring='%s_macro' % score) #cv为迭代次数。#基于交叉验证的网格搜索,cv:确定交叉验证拆分策略。
    # 用训练集训练这个学习器 clf
    clf.fit(X_train, y_train)
  
    print("Best parameters set found on development set:")
    print()
  
    # 再调用 clf.best_params_ 就能直接得到最好的参数搭配结果
    print(clf.best_params_)
     
    print()
    print("Grid scores on development set:")
    print()
    means = clf.cv_results_['mean_test_score']
    stds = clf.cv_results_['std_test_score']
  
    # 看一下具体的参数间不同数值的组合后得到的分数是多少
    for mean, std, params in zip(means, stds, clf.cv_results_['params']):
        print("%0.3f (+/-%0.03f) for %r"
             % (mean, std * 2, params))
  
    print()
  
    print("Detailed classification report:")
    print()
    print("The model is trained on the full development set.")
    print("The scores are computed on the full evaluation set.")
    print()
    y_true, y_pred = y_test, clf.predict(X_test)
   
    # 打印在测试集上的预测结果与真实值的分数
    print(classification_report(y_true, y_pred))
   
    print()

以上代码可以得出最优的参数组合,

3、训练模型

我用的是sklearn包中封装好的SVC()算法,利用了10折交叉检验和ROC曲线来评价模型,代码如下:

#交叉验证+roc曲线
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import StratifiedKFold
 
#交叉验证
cv = StratifiedKFold(n_splits=10)    #导入该模型,后面将数据划分6份
classifier = svm.SVC(kernel='rbf',gamma=0.0001,C=1000, probability=True,random_state=0)   # SVC模型 可以换作AdaBoost模型试试
  
# 画平均ROC曲线的两个参数
mean_tpr = 0.0              # 用来记录画平均ROC曲线的信息
mean_fpr = np.linspace(0, 1, 100)
cnt = 0
for i, (train, test) in enumerate(cv.split(X,Y)):       #利用模型划分数据集和目标变量 为一一对应的下标
    cnt +=1
    probas_ = classifier.fit(X[train], Y[train]).predict_proba(X[test]) # 训练模型后预测每条样本得到两种结果的概率
    fpr, tpr, thresholds = roc_curve(Y[test], probas_[:, 1])    # 该函数得到伪正例、真正例、阈值,这里只使用前两个
  
    mean_tpr += np.interp(mean_fpr, fpr, tpr)   # 插值函数 interp(x坐标,每次x增加距离,y坐标)  累计每次循环的总值后面求平均值
    mean_tpr[0] = 0.0           # 将第一个真正例=0 以0为起点
  
    roc_auc = auc(fpr, tpr)  # 求auc面积
    plt.plot(fpr, tpr, lw=1, label='ROC fold {0:.2f} (area = {1:.2f})'.format(i, roc_auc))    # 画出当前分割数据的ROC曲线
  
plt.plot([0, 1], [0, 1], '--', color=(0.6, 0.6, 0.6), label='Luck') # 画对角线
  
mean_tpr /= cnt   # 求数组的平均值
mean_tpr[-1] = 1.0   # 坐标最后一个点为(1,1)  以1为终点
mean_auc = auc(mean_fpr, mean_tpr)
  
plt.plot(mean_fpr, mean_tpr, 'k--',label='Mean ROC (area = {0:.2f})'.format(mean_auc), lw=2)
  
plt.xlim([-0.05, 1.05])     # 设置x、y轴的上下限,设置宽一点,以免和边缘重合,可以更好的观察图像的整体
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')    # 可以使用中文,但需要导入一些库即字体
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

4、模型保存

如果想要将训练好的模型保存下来,可以用以下代码:

#保存模型
from sklearn.externals import joblib
os.chdir("G:/Download_Data_bishe/save_model")
joblib.dump(classifier,"train_model.m")

其实我还是很疑惑10折交叉检验到底是用来评价模型的还是用来选择最优模型的???

最后,放一张结果图

SVM的识别效果还是可以的,不过也可能我的数据集不大的原因。

三、完整代码如下:

#SVM算法

import datetime
starttime = datetime.datetime.now()

import numpy as np
import os
import cv2
import sklearn.model_selection as ms
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, classification_report

X = []
Y = []

for i in range(0, 2):
    #遍历文件夹,读取图片
    for f in os.listdir("G:/Download_Data_bishe/leaf_data/pepper_bellSmall/%s" % i):
        #打开一张图片并灰度化
        Images = cv2.imread("G:/Download_Data_bishe/leaf_data/pepper_bellSmall/%s/%s" % (i, f)) 
        image=cv2.resize(Images,(256,256),interpolation=cv2.INTER_CUBIC)
        hist = cv2.calcHist([image], [0,1], None, [256,256], [0.0,255.0,0.0,255.0]) 
        X.append(((hist/255).flatten()))
        Y.append(i)
X = np.array(X)
Y = np.array(Y)

#切分训练集和测试集
#X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=1)
#随机率为100%选取其中的30%作为测试集

#交叉验证+roc曲线
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import StratifiedKFold
 
#交叉验证
cv = StratifiedKFold(n_splits=10)    #导入该模型,后面将数据划分6份
classifier = svm.SVC(kernel='rbf',gamma=0.0001,C=1000, probability=True,random_state=0)   # SVC模型 可以换作AdaBoost模型试试
  
# 画平均ROC曲线的两个参数
mean_tpr = 0.0              # 用来记录画平均ROC曲线的信息
mean_fpr = np.linspace(0, 1, 100)
cnt = 0
for i, (train, test) in enumerate(cv.split(X,Y)):       #利用模型划分数据集和目标变量 为一一对应的下标
    cnt +=1
    probas_ = classifier.fit(X[train], Y[train]).predict_proba(X[test]) # 训练模型后预测每条样本得到两种结果的概率
    fpr, tpr, thresholds = roc_curve(Y[test], probas_[:, 1])    # 该函数得到伪正例、真正例、阈值,这里只使用前两个
  
    mean_tpr += np.interp(mean_fpr, fpr, tpr)   # 插值函数 interp(x坐标,每次x增加距离,y坐标)  累计每次循环的总值后面求平均值
    mean_tpr[0] = 0.0           # 将第一个真正例=0 以0为起点
  
    roc_auc = auc(fpr, tpr)  # 求auc面积
    plt.plot(fpr, tpr, lw=1, label='ROC fold {0:.2f} (area = {1:.2f})'.format(i, roc_auc))    # 画出当前分割数据的ROC曲线
  
plt.plot([0, 1], [0, 1], '--', color=(0.6, 0.6, 0.6), label='Luck') # 画对角线
  
mean_tpr /= cnt   # 求数组的平均值
mean_tpr[-1] = 1.0   # 坐标最后一个点为(1,1)  以1为终点
mean_auc = auc(mean_fpr, mean_tpr)
  
plt.plot(mean_fpr, mean_tpr, 'k--',label='Mean ROC (area = {0:.2f})'.format(mean_auc), lw=2)
  
plt.xlim([-0.05, 1.05])     # 设置x、y轴的上下限,设置宽一点,以免和边缘重合,可以更好的观察图像的整体
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')    # 可以使用中文,但需要导入一些库即字体
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()


#保存模型
from sklearn.externals import joblib
os.chdir("G:/Download_Data_bishe/save_model")
joblib.dump(classifier,"train_model.m")

# #只有交叉验证
# clf = SVC(kernel='rbf',gamma=0.001,C=100)
# scores = cross_val_score(clf, X , Y , cv=5)  #cv为迭代次数。
# print(scores)  # 打印输出每次迭代的度量值(准确度)
# print(scores.mean())
# print()



#普通的一次性模型训练预测
#clf = SVC(kernel='rbf',gamma=0.001,C=100)
# clf.fit(X_train, y_train)#训练
# predictions0 = clf.predict(X_test)
# #predictions0=pred_test_y
# print(confusion_matrix(y_test, predictions0))
# print (classification_report(y_test, predictions0))
# endtime = datetime.datetime.now()
# print (endtime - starttime)


# #自动调参函数
# tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
#                       'C': [1, 10, 100, 1000]},
#                     {'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]
# scores = ['precision', 'recall']
# for score in scores:
#     print("# Tuning hyper-parameters for %s" % score)
#     print()
#   
#     # 调用 GridSearchCV,将 SVC(), tuned_parameters, cv=5, 还有 scoring 传递进去,
#     clf = ms.GridSearchCV(svm.SVC(), tuned_parameters, cv=10,
#                        scoring='%s_macro' % score) #cv为迭代次数。#基于交叉验证的网格搜索,cv:确定交叉验证拆分策略。
#     # 用训练集训练这个学习器 clf
#     clf.fit(X_train, y_train)
#   
#     print("Best parameters set found on development set:")
#     print()
#   
#     # 再调用 clf.best_params_ 就能直接得到最好的参数搭配结果
#     print(clf.best_params_)
#      
#     print()
#     print("Grid scores on development set:")
#     print()
#     means = clf.cv_results_['mean_test_score']
#     stds = clf.cv_results_['std_test_score']
#   
#     # 看一下具体的参数间不同数值的组合后得到的分数是多少
#     for mean, std, params in zip(means, stds, clf.cv_results_['params']):
#         print("%0.3f (+/-%0.03f) for %r"
#              % (mean, std * 2, params))
#   
#     print()
#   
#     print("Detailed classification report:")
#     print()
#     print("The model is trained on the full development set.")
#     print("The scores are computed on the full evaluation set.")
#     print()
#     y_true, y_pred = y_test, clf.predict(X_test)
#    
#     # 打印在测试集上的预测结果与真实值的分数
#     print(classification_report(y_true, y_pred))
#    
#     print()


 

  • 15
    点赞
  • 231
    收藏
    觉得还不错? 一键收藏
  • 38
    评论
SVM(支持向量机)是一种用于二分类问题的机器学习算法。其流程图如下: 1. 数据准备:收集包含已标记的二分类数据的训练集。每个数据点都有一组与之相关的特征和一个二分类的标签。 2. 特征提取:对训练集中的每个数据点进行特征提取,将其转换为可以被机器学习算法处理的形式。 3. 特征缩放:对提取得到的特征进行缩放,使其具有相似的尺度,以避免某些特征对结果产生更大的影响。 4. 参数选择:选择用于训练SVM模型的参数,如核函数类型、惩罚参数等。这些参数的选择会影响模型的性能。 5. 模型训练:使用训练集对SVM模型进行训练。训练过程是通过将数据映射到高维空间中,找到一个最优的分离超平面来实现的。 6. 模型评估:使用测试集对训练得到的SVM模型进行评估,计算分类准确率、精确率、召回率等指标来评估模型的性能。 7. 超参数调优:根据评估结果,对模型的超参数进行调优,如调整惩罚参数的大小,再次训练模型。 8. 模型预测:使用优化后的模型对未知的数据进行预测。将输入数据映射到高维空间并根据找到的分离超平面进行分类,预测数据的标签。 9. 结果解释:根据模型的预测结果进行解释和分析,评估模型是否满足实际需求。 SVM流程图可帮助我们理解SVM的工作原理和实施过程,从数据准备到模型预测,每个步骤都至关重要,并且可以通过调整参数和优化模型来提高分类性能。
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值