版权声明:本文为博主原创文章,转载请注明作者和出处。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 Trueexcept: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两个参数