《opencv》5.1

本节的例子是利用决策树根据病人的一些生理指标数据决定开什么药品,药品一共四种,分别是A、B、C、D。而病人的生理指标有年龄、性别、血压、胆固醇指标、血液中Na浓度、血液中K浓度。所有的数据如下:
data = [
{‘age’: 33, ‘sex’: ‘F’, ‘BP’: ‘high’, ‘cholesterol’: ‘high’, ‘Na’: 0.66, ‘K’: 0.06, ‘drug’: ‘A’},
{‘age’: 77, ‘sex’: ‘F’, ‘BP’: ‘high’, ‘cholesterol’: ‘normal’, ‘Na’: 0.19, ‘K’: 0.03, ‘drug’: ‘D’},
{‘age’: 88, ‘sex’: ‘M’, ‘BP’: ‘normal’, ‘cholesterol’: ‘normal’, ‘Na’: 0.80, ‘K’: 0.05, ‘drug’: ‘B’},
{‘age’: 39, ‘sex’: ‘F’, ‘BP’: ‘low’, ‘cholesterol’: ‘normal’, ‘Na’: 0.19, ‘K’: 0.02, ‘drug’: ‘C’},
{‘age’: 43, ‘sex’: ‘M’, ‘BP’: ‘normal’, ‘cholesterol’: ‘high’, ‘Na’: 0.36, ‘K’: 0.03, ‘drug’: ‘D’},
{‘age’: 82, ‘sex’: ‘F’, ‘BP’: ‘normal’, ‘cholesterol’: ‘normal’, ‘Na’: 0.09, ‘K’: 0.09, ‘drug’: ‘C’},
{‘age’: 40, ‘sex’: ‘M’, ‘BP’: ‘high’, ‘cholesterol’: ‘normal’, ‘Na’: 0.89, ‘K’: 0.02, ‘drug’: ‘A’},
{‘age’: 88, ‘sex’: ‘M’, ‘BP’: ‘normal’, ‘cholesterol’: ‘normal’, ‘Na’: 0.80, ‘K’: 0.05, ‘drug’: ‘B’},
{‘age’: 29, ‘sex’: ‘F’, ‘BP’: ‘high’, ‘cholesterol’: ‘normal’, ‘Na’: 0.35, ‘K’: 0.04, ‘drug’: ‘D’},
{‘age’: 53, ‘sex’: ‘F’, ‘BP’: ‘normal’, ‘cholesterol’: ‘normal’, ‘Na’: 0.54, ‘K’: 0.06, ‘drug’: ‘C’},
{‘age’: 36, ‘sex’: ‘F’, ‘BP’: ‘high’, ‘cholesterol’: ‘high’, ‘Na’: 0.53, ‘K’: 0.05, ‘drug’: ‘A’},
{‘age’: 63, ‘sex’: ‘M’, ‘BP’: ‘low’, ‘cholesterol’: ‘high’, ‘Na’: 0.86, ‘K’: 0.09, ‘drug’: ‘B’},
{‘age’: 60, ‘sex’: ‘M’, ‘BP’: ‘low’, ‘cholesterol’: ‘normal’, ‘Na’: 0.66, ‘K’: 0.04, ‘drug’: ‘C’},
{‘age’: 55, ‘sex’: ‘M’, ‘BP’: ‘high’, ‘cholesterol’: ‘high’, ‘Na’: 0.82, ‘K’: 0.04, ‘drug’: ‘B’},
{‘age’: 35, ‘sex’: ‘F’, ‘BP’: ‘normal’, ‘cholesterol’: ‘high’, ‘Na’: 0.27, ‘K’: 0.03, ‘drug’: ‘D’},
{‘age’: 23, ‘sex’: ‘F’, ‘BP’: ‘high’, ‘cholesterol’: ‘high’, ‘Na’: 0.55, ‘K’: 0.08, ‘drug’: ‘A’},
{‘age’: 49, ‘sex’: ‘F’, ‘BP’: ‘low’, ‘cholesterol’: ‘normal’, ‘Na’: 0.27, ‘K’: 0.05, ‘drug’: ‘C’},
{‘age’: 27, ‘sex’: ‘M’, ‘BP’: ‘normal’, ‘cholesterol’: ‘normal’, ‘Na’: 0.77, ‘K’: 0.02, ‘drug’: ‘B’},
{‘age’: 51, ‘sex’: ‘F’, ‘BP’: ‘low’, ‘cholesterol’: ‘high’, ‘Na’: 0.20, ‘K’: 0.02, ‘drug’: ‘D’},
{‘age’: 38, ‘sex’: ‘M’, ‘BP’: ‘high’, ‘cholesterol’: ‘normal’, ‘Na’: 0.78, ‘K’: 0.05, ‘drug’: ‘A’}
]

drug这一列是我们的target,即分类目标,把它提取出来,并且量化为数值。
target = [d[‘drug’] for d in data]
target = [ord(t) - 65 for t in target]
量化后,target的结果为:
[0, 3, 1, 2, 3, 2, 0, 1, 3, 2, 0, 1, 2, 1, 3, 0, 2, 1, 3, 0]

除了target外,我们需要讲所有的文本特征转换为数值特征,使用sciket-learn中的DictVectorizer完成:
vec = DictVectorizer(sparse=False)
data_pre = vec.fit_transform(data)

之后将数据分成训练和测试两部分:
x_train, x_test, y_train, y_test = ms.train_test_split(data_pre, target, test_size = 5, random_state = 42)

此时就可以使用决策树的训练模型对数据进行训练和预测了。书中使用的是opencv提供的决策树模型实际是3.1版本之前的方法了,当前版本需要使用DTrees_create()创建。实际上sciket-learn也提供了决策树模型,而且更加优秀,用书中的话就是:可以让我们对算法进行定制化,并且可以更简单的对决策树的内部工作了流程进行探索。
权衡后,决定以后所有的机器学习模型都是用sciket-learn中提供的。
dtc = tree.DecisionTreeClassifier(criterion=‘entropy’, max_leaf_nodes=6)
dtc.fit(x_train, y_train)

使用模型对测试数据和训练数据进行预测,得到结果分别是1.0和0.4。很明显,模型出现了过拟合现象,泛化能力不足。
dtc.score(x_train, y_train)
dtc.score(x_test, y_test)

我们对决策树进行可视化,如下图:
在这里插入图片描述可以看到每一个决策条件都是data中的一个特征,每一次决策的结果都是将输入数据分成两份,而树的叶节点都是最终的分类结果。

那么问题来了,决策树是如何决定树中节点选择哪个 特征做为判断条件的呢?
scikit-learn提供了方法判断特征的重要性,它会对每个特征返回一个0到1之间的数字,0表示所有决策都不使用这个特征,而1表示这个特征可以完美的预测这个目标。这些特征的结果会归一化。本例中的结果:
[0. 0. 0. 0. 0.5105994 0.18687375 0. 0.30252685 0. 0. ]
[‘BP=high’, ‘BP=low’, ‘BP=normal’, ‘K’, ‘Na’, ‘age’, ‘cholesterol=high’, ‘cholesterol=normal’, ‘sex=F’, ‘sex=M’]
在这里插入图片描述
可以看到重要性值最大的是Na这个特征,而决策树中可以看到该指标是作为根节点的判断依据。不过需要说明的是,决策树节点判断条件的选择并不完全是依照重要性来的。

那么特征的重要性是如何得来的呢?
评判的标准主要是特性的信息性的大小,一个特征的信息性越多,则该特征就越重要。
那么信息性又是如何评判的呢?
scikit-learn提供了两种标准,也是最常用的标准,分别是基尼不纯度和信息熵。前者是一个错误分类的的测量,即最小化错误分类的概率。而后者中熵在信息论中是一个信号或者分布的不确定度的测量,一个完美的数据分割的熵为0。
上述的运行结果采用的标准都是信息熵。如果改成基尼不纯度,特征重要性结果是不一样的。
在这里插入图片描述
但是预测的结果依然是0.4,模型过拟合的问题依然存在。但是数据量太少,无法做进一步的解析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Qt 上实现人脸识别打卡的功能,可以使用 OpenCV 库来进行人脸检测、特征提取和匹配等操作。以下是一个简单的流程: 1. 采集人脸照片:使用摄像头或者从文件中读取照片,获取人脸照片。 2. 人脸检测和特征提取:使用 OpenCV 的人脸检测和特征提取算法,对人脸照片进行处理,提取出人脸的特征向量。 3. 特征匹配:将当前人脸的特征向量与之前采集的人脸特征向量进行比对,判断是否匹配。 4. 打卡记录:根据匹配结果,记录打卡时间和结果,可以将记录保存到数据库中。 下面是一个简单的示例代码,演示如何使用 OpenCV 进行人脸识别: ```cpp // 匹配阈值 const double threshold = 0.7; // 人脸检测器 cv::CascadeClassifier face_cascade; face_cascade.load("haarcascade_frontalface_alt.xml"); // 特征提取器 cv::Ptr<cv::face::LBPHFaceRecognizer> recognizer = cv::face::LBPHFaceRecognizer::create(); // 数据库 QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("localhost"); db.setDatabaseName("test"); db.setUserName("root"); db.setPassword("123456"); db.open(); // 初始化打卡表 QSqlQuery query(db); query.exec("CREATE TABLE IF NOT EXISTS attendance (" "id INT PRIMARY KEY AUTO_INCREMENT," "name VARCHAR(100)," "time DATETIME," "result VARCHAR(20)" ")"); // 获取当前时间 QDateTime current = QDateTime::currentDateTime(); // 采集人脸照片 cv::Mat frame = ...; // 人脸检测 std::vector<cv::Rect> faces; cv::Mat gray; cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); face_cascade.detectMultiScale(gray, faces, 1.1, 2, 0, cv::Size(30, 30)); // 特征提取和匹配 for (const cv::Rect& face : faces) { cv::Mat face_roi = gray(face); cv::resize(face_roi, face_roi, cv::Size(100, 100)); int label = -1; double confidence = 0; recognizer->predict(face_roi, label, confidence); QString name; if (confidence < threshold) { // 匹配成功 QSqlQuery query(db); query.prepare("SELECT name FROM faces WHERE id = ?"); query.addBindValue(label); query.exec(); if (query.next()) { name = query.value(0).toString(); } QString result = "Success"; query.prepare("INSERT INTO attendance (name, time, result) VALUES (?, ?, ?)"); query.addBindValue(name); query.addBindValue(current.toString("yyyy-MM-dd hh:mm:ss")); query.addBindValue(result); query.exec(); } else { // 匹配失败 QString result = "Failed"; query.prepare("INSERT INTO attendance (name, time, result) VALUES (?, ?, ?)"); query.addBindValue(""); query.addBindValue(current.toString("yyyy-MM-dd hh:mm:ss")); query.addBindValue(result); query.exec(); } } ``` 在这个代码片段中,我们使用了 OpenCV 的人脸检测器和特征提取器来进行人脸识别,使用了 Qt 的数据库 API 来记录打卡记录。具体来说,我们首先加载了人脸检测器和特征提取器,并初始化了数据库。然后我们获取当前时间,并采集人脸照片。接着我们使用人脸检测器检测人脸,使用特征提取器提取人脸特征向量,并与之前采集的特征向量进行比对,判断匹配度是否达到阈值。如果匹配成功,我们从数据库中获取该人的姓名,并将打卡记录插入到数据库中。如果匹配失败,我们将打卡记录插入到数据库中,并将姓名设置为空字符串。 需要注意的是,这只是一个简单的示例代码,实际应用中还需要考虑更多的实现细节和安全性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值