版权声明:本文为博主原创文章,转载请注明作者和出处。https://blog.csdn.net/xq920831/article/details/84390468
参考文章地址:https://blog.csdn.net/qq_42379006/article/details/80929670
决策树与随机森林的基础知识:https://www.cnblogs.com/fionacai/p/5894142.html
首先制作好自己的图片集:文件夹——各类别小文件夹——各类图片。
下面就是代码部分:
# -*- coding:utf-8 -*-
# Author: Agent Xu
# 导入模块
import numpy as np
import cv2
import os
import glob
from skimage import io,transform
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix,precision_recall_fscore_support
import pandas as pd
import pickle
#将所有的图片resize成100*100
w = 100
h = 100
# 创建模型输出文件夹
output_dir='output'
if not os.path.exists(output_dir):
os.mkdir(output_dir)
# 数据准备 - 读取图片并贴标签
img_dir = 'D:/GJAI_data/gongjingai_pre/tupian/'
#读取图片
def read_img(path):
cate = [path+x for x in os.listdir(path) if os.path.isdir(path+x)]
imgs = []
labels = []
for idx,folder in enumerate(cate):
for im in glob.glob(folder+'/*.jpg'):
print('reading the images:%s'%(im))
img = cv2.imread(im,cv2.IMREAD_COLOR)
# img = transform.resize(img,(w,h))
imgs.append(img)
labels.append(idx)
# return np.asarray(imgs,np.float32),np.asarray(labels,np.int32)
return imgs,labels
# for fname in os.listdir(img_dir):
# '''跳过不是目标图片的文件'''
# if not fname.startswith('image'):continue
# '''
# 合并目录:os.path.join
# import os
# os.path.join('/hello/','good/boy/','doiido')
# >>> '/hello/good/boy/doiido'
# '''
# fpath = os.path.join(img_dir,fname)
# '''根据文件名,提取图片分类'''
# lab = fpath.split('_')[1]
# '''RGB模式读取图片,读入的图片得到的是ndarray对象,0~255的整数'''
# img = cv2.imread(fpath,cv2.IMREAD_COLOR)
# images.append(img)
# labels.append(lab)
'''定义特征转化函数'''
def transform1(img):
'''每个通道等分为8组后计算直方图'''
hist = cv2.calcHist([img],[0,1,2],None,[8,8,8],[0,256,0,256,0,256])
'''将8*8*8的多维数组拉平'''
return hist.ravel()
'''
保存模型:
通常情况下在一个地方训练的模型都会在另外一个地方被使用,因此每次训练的模型都需要保存成一个可调用的对象
本例中采用pickle.dump()方法将训练的模型保存,然后可以实现在其他地方调用,以此方便模型的使用
'''
def save_model(model,label_encoder,output_file):
try:
with open(output_file,'wb') as outfile:
pickle.dump({
'model':model,
'label_encoder':label_encoder
},outfile)
return True
except:
return False
'''计算各项评价指标'''
def eval_model(y_true,y_pred,labels):
'''计算每个分类器的Precision,Recall,f1,support'''
P,r,f1,s =precision_recall_fscore_support(y_true,y_pred)
'''计算总体平均的Precision,Recall,f1,support'''
tot_P = np.average(P,weights =s)
tot_r = np.average(r,weights =s)
tot_f1 = np.average(f1,weights =s)
tot_s = np.sum(s)
res1 = pd.DataFrame({
'Label':labels,
'Precision':P,
'Reacll':r,
'F1':f1,
'Support':s
})
res2 = pd.DataFrame({
'Label':['总体'],
'Precision':[tot_P],
'Recall':[tot_r],
'F1':[tot_f1],
'Support':[tot_s]
})
res2.index=[999]
res = pd.concat([res1,res2])
'''计算混淆矩阵'''
conf_mat = pd.DataFrame(confusion_matrix(y_true,y_pred),columns=labels,index=labels)
return conf_mat,res[['Label','Precision','Recall','F1','Support']]
images,labels = read_img(img_dir)
'''将图片标签ID化,输出可由计算机处理的数据,四种花,四种标签,此处相当于多分类问题'''
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(labels)
'''训练集、测试集划分,stratify = y,表示根据图片类别进行分类,确保每个类别图片的均衡性'''
train_idx,test_idx = train_test_split(range(len(y)),test_size=0.2,stratify = y, random_state = 1234) # 返回拆分后的索引
train_y = y[train_idx]
test_y = y[test_idx]
# 计算RGB颜色直方图
'''提取每个图像的直方图特征,按行合并成一个大的矩阵,每一行即一张图片的长度为512特征'''
x_rgb = np.row_stack([transform1(img) for img in images])
'''
根据索引取得处理后的图片分别存入训练集和测试集
x[[],:]:取得对应行数的所有列数据
'''
train_x = x_rgb[train_idx,:]
test_x = x_rgb[test_idx,:]
#使用随机森林分类器
model_rgb_rf = RandomForestClassifier(n_estimators =50, max_depth =7, random_state=None) # 1234随机初始化的种子
model_rgb_rf.fit(train_x,train_y) # 训练数据集
# 保存模型
save_model(model_rgb_rf,label_encoder,os.path.join(output_dir,'model_rgb_rf.pkl'))
#随机森林模型评估
'''在测试集上计算每个图片的预测分类'''
y_pred_rgb_rf = model_rgb_rf.predict(test_x)
'''评估模型'''
conf_mat_lab_rf,evalues_rf = eval_model(test_y,y_pred_rgb_rf,label_encoder.classes_)
#使用逻辑回归训练分类器
'''l2正则惩罚项,惩罚力度为1'''
model_rgb_lr = LogisticRegression(penalty ='l2',C=1,random_state=1234)
model_rgb_lr.fit(train_x,train_y)
# 保存模型
save_model(model_rgb_lr,label_encoder,os.path.join(output_dir,'model_rgb_lr.pkl'))
#逻辑回归模型评估
'''在测试集上计算每个图片的预测分类'''
y_pred_rgb_lr = model_rgb_lr.predict(test_x)
'''评估模型'''
conf_mat_rgb_lr,evalues_rgb_lr = eval_model(test_y,y_pred_rgb_lr,label_encoder.classes_)
重点是调参部分
随机森林:RandomForestClassifier函数
根据自身数据集调节n_estimators和max_depth参数,其次min_samples_split和min_samples_leaf调参(可加可不加)
逻辑回归:LogisticRegression函数
调节penalty和C两个参数