10. 机器学习-评测指标

茶桁的AI秘籍 10

Hi,你好。我是茶桁。

之前的课程中,我们学习了两个最重要的回归方法,一个线性回归,一个逻辑回归。也讲解了为什么学习机器学习要从逻辑回归和线性回归讲起。因为我们在解决问题的时候,有限选择简单的假设,越复杂的模型出错的概率也就越高。

本节课中,我们要继续我们未完成的内容。

还记得,咱们上一节课中最后所说的吗?在完成了基本回归之后,该如何去判断一个模型的好坏,以及如何调整和优化。

好,我们开始本节课程。

PICKLE

本节课中,会重点的给大家做一件事,叫「评测指标」。

在这之前,我们发现了一个麻烦事。就是我们现在需要去观测我们的分类结果,我们不得不再去执行一遍我们之前的训练程序,拿到最后的分类结果:

RM:6.38, LSTAT:24.08, EXPENSIVE:0, Predicated:0
...
RM:6.319, LSTAT:11.1, EXPENSIVE:1, Predicated:0

这很麻烦,训练结果每次要使用的时候都需要运行一次,这样非常的麻烦。现在我想要把这个model不要每一次都训练一下,而是要把它做一个保存,下次用的时候不需要从头到尾再训练一次。

现在现在,可以给他做一个persistence,做一个留存。现在就是要做这么一件事情。

import picklewith open('logistic_regression.model', 'wb') as f:pickle.dump(model, f)with open('w.model', 'wb') as f:pickle.dump(w, f)with open('b.model', 'wb') as f:pickle.dump(b, f)print('pickle finished')---
pickle finished

并且最后我得到了三个文件,分别是logistic_regression.model, w.model以及b.model

在这里插入图片描述

现在就可以把训练完成的model做保存了。之后我们用Pytorch, tenserflow之类的做,它都有这样的功能。

到这一步之后,我们上一节上所写的代码就可以暂时不用了。不过为了整个代码的完整性,我仍然将其又在本节课的10.ipynb内些了一遍。

那么,我们要用的时候怎么办呢?如果要用这个对象的时候,将我们之前对文件操作的代码拿过来,然后将其中的wb参数改成rb,然后再将二进制文件读取一遍:

with open('logistic_regression.model', 'rb') as f:model_r = pickle.load(f)with open('w.model', 'rb') as f:w_r = pickle.load(f)with open('b.model', 'rb') as f:b_r = pickle.load(f)print('pickle read finished')

rb的意思是read binary,也就是读取二进制文件。然后,为了在测试的时候避免混乱,让我接下来所使用的文件使用的是我重新读取的模型而不是之前训练时生成的的,我将重新读取的这几个文件命名为model_rw_r,b_r

那再之后,虽然不用重新训练了,但是数据还是要读取一遍的,并且,按照训练数据的规则重新整理好, 都完善了之后,就可以开搞进行分类了。

import pandas as pd
from sklearn.datasets import fetch_openmldataset = fetch_openml(name='boston', version=1, as_frame=True, return_X_y=False, parser='pandas')data = dataset['data']
target = dataset['target']dataframe = pd.DataFrame(data)rm = dataframe['RM']
lstat = dataframe['LSTAT']
dataframe['price'] = dataset['target']greater_then_most = np.percentile(dataframe['price'], 66)
dataframe['expensive'] = dataframe['price'].apply(lambda p: int(p > greater_then_most))expensive = dataframe['expensive']
random_test_indices = np.random.choice(range(len(rm)), size=100)
decision_boundary = 0.5for i in random_test_indices:x1, x2, y = rm[i], lstat[i], expensive[i]predicate = model_r(np.array([x1, x2]), w_r, b_r)predicate_label = int(predicate > decision_boundary)print('RM:{}, LSTAT:{}, EXPENSIVE:{}, Predicated:{}'.format(x1, x2, y, predicate_label))

评测指标

好,解决了模型的重复使用之后,我们再回到课程中继续。

很多人在学习过程中,会觉得「评测指标」是一个没有那么有趣的事情。比方说,咱们学模型,学算法,就可以去写程序,可以运行,写出来的时候会感觉还蛮酷的。但是评测指标呢,很多同学就觉得不是那么有趣。

其实,我想告诉大家,评测指标是一个非常重要的东西。好比完成任何一个任务,不管你现在是完成普通的编程任务,还是要完成一个公司的市场行为、运营行为。一般来说,越复杂的任务,只要把评价指标,评价方式做对,这个任务基本上就已经完成了一半了。

对于我们来说,工作的时候要知道,对于一个机器学习任务,能找到正确的评测指标,这个机器学习任务就已经成功一半了。

首先,来看一个问题:Losses持续下降,到底是意味着什么呢?

import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(losses)

在这里插入图片描述

loss持续下降意味着误差越来越小?方向是对的?测试值更加接近真实值?更精确的说法是,它在逼近最优解,但是效果是不是特别好,还不知道。

接下来这个问题是一个比较复杂的问题,是一个难点:

-np.sum(y * np.log(yhat) + (1 - y) * np.log(1 - yhat))

这段代码是我们写的loss函数, 我们现在来假设有一组数据:

true_label = np.array([1, 0, 1, 0, 1]) # 二分类

再假设有一个模型,在执行的时候,它会知道咱们做的是一个二分类问题,那么结果就是不是1,就是0。这个时候模型有可能偷懒,那给到的数据就会是随机的,好吧,开个玩笑,其实就只是因为数据不足造成给到的数据过于随机:

predicate_1 = np.array([0.8, 0.7, 0.8, 0.3, 0.8])

然后我们执行算法来拿到结果:

def test_lose(y, yhat):return -np.sum(y * np.log(yhat) + (1 - y) * np.log(1 - yhat))
test_lose(true_label, predicate_1)---
2.2300784022072975

现在我们拿到的值为2.23,不过要记得,咱们这只是一个假设值。那这个时候引入我们刚才谈到的loss的曲线,loss是持续下降的,当它下降到最低的值的时候依然比这个2.23还要高,那就说明这个模型都还没有随机猜测的准确度高。

这个情况其实是经常会遇到的一个问题,你会看到你的的模型一直在下降,下降的非常好,但是一做实际测试的时候效果就特别差。

再换个说法就是,这个模型跑的时候,瞎猜的值都有2.23的准确,但是loss虽然一只在下降,一只下降到了3。虽然loss看起来在下降,但是这整个结果都不是太好。

瞎猜的时候的准确度,loss值,我们称为这个模型的Baseline。你的值最起码要比这个好。

所以就如之前所的,loss持续下降意味着模型在向着最优的方向在寻找,但并不意味着结果就会很好,因为有可能连瞎猜都不如。

好,以上是第一点,我们接着来看第二点。

loss一直在下降,但是我们现在想知道的是有多少个label预测对了。先建立两个变量来分别存储数据:

true_labels, predicated_labels = [], []...
for i in random_test_indices:...true_labels.append(y)predicated_labels.append(predicate_label)

然后分别获得了两组数据,一个是true_labels,一个是predicated_labels。有了这两组数据之后,我们来定义一个accuracy, 这个是预测的值和相似的值一共有多少个是一样的。

def accuracy(ytrues, ylabels):return sum(1 for yt, y1 in zip(ytrues, ylabels) if yt == y1) / len(ytrues)accuracy(true_labels, precicated_labels)---
0.89

0.89, 就是说有89%的label都是猜对了。

最早的时候其实只有这一个标记,但这个标记很容易出错。

假设有一个警察局,要在100个人里边判断谁是犯罪分子。现在我们知道有3个是犯罪分子,然后警察说这100个人全部都是犯罪分子。那么现在准确度有多少?

然后又有一个警察站出来说,这100个人都不是犯罪分子,那他的准确度又是多少?

我们现在让第一个警察是a,第二个警察是b。

警察b有97个标签都说对了,这会给人一种错觉,好像他预测的很准确的。但是其实,a和b两个人都判断的不准确。那我们这个时候就需要引出一个定义:Precision。

precision也是准确度的意思,和accuracy不同点是,accuracy的对比是对比目标和现有值是否匹配,匹配的就算正确。而precision除了看是否匹配之外,还要目标值,也就是positive。

这里举个例子说明一下,比如我们去检测是否有新冠病毒,那么目标是为了检测出有新馆病毒的人,那么呈阳性的人就是我们的positive, 那么我们precision除了预测出有新冠和没有新冠的人之外,有新冠的人也需要一一对应上,也就是positive要正确。

如果是写代码的话,也就是将之前的accuracy拿过来改改就可以直接用了:

def precision(ytrues, yhats):# 预测标签是1的里面,正确的比例是多少positives_pred = [y for y in yhats if y == 1]return sum(1 for yt, y in zip(ytrues, yhats) if yt == y and y == 1) / len(positives_pred)precision(true_labels, predicated_labels)---
0.8333333333333334

先将预测为1,也就是预测呈阳性的目标放到positives_pred中,再来检测一下在这些预测出来的目标中,预测对的有多少。

除此之外之外,还有一个值叫做recall,它的意思是在实际的positive里,有多少比例被找到了。

def recall(ytrues, yhats):true_positive = [y for y in ytrues if y == 1]     return sum(1 for yt, y in zip(ytrues, yhats) if yt == y and yt == 1) / len(true_positive)recall(true_labels, predicated_labels)---
0.8064516129032258

好,我们再来复盘一下这三个值,一个是accuracy, 一个是precision,一个是recall

accuracy就是预测值和实际值有多少是一样的。但是有可能会在实际场景都不是很均衡。

precision是拿到预测后的目标值,然后拿这些目标的实际值去比较看有多大比例是一样的。

recall是先拿到实际的目标值,然后拿目标预测值比较看有多大比例是一样的。

根据我们之前说的警察抓坏人的那个假设,我们现在来做一个测试,假设我们现在好人有90个,坏人有10个。

people = [0] * 90 + [1] * 10
import random
random.shuffle(people)

现在警察a来了,就判断说:全部都是好人,把他们全部都放了吧。这样的话,它的accuracy是多少呢?accuracy就是预测的,只要是实际值的那个label就行。我们来看看:

a = [0] * 100
accuracy(people, a)---
0.9

我们看这个准确度就会很高,这个也能理解,因为警察a将这100个人中的90个好人全部判断准确了对吧?

让我们来看看其他两个:

precision(people, a)---
ZeroDivisionError: division by zero======
recall(people, a)---
0

precision警告我们分母为0,报错了。那分母为什么为0呢?因为a说了,所有都是好人,那么预测的目标值,也就是分母上的坏人就为0。

而recall呢,结果为0。这是因为分母上的坏人实际值虽然为10,但是预测的目标值,也就是分子上为0。那结果肯定是为0。

本来a的accuracy是0.9,别人还以为准确度很高,结果一个坏人都没抓住。这肯定不行。

那b的情况又如何呢?之前说过,b说所有的都是坏人,统统抓起来。

b = [1] * 100
accuracy(people, b)---
0.1========
precision(people, b)---
0.1=========
recall(people, b)---
1.0

虽然accuracyprecision都不高,但是似乎目标都被找出来了。颇有一种「宁可错杀1000,不可放过一个」的感觉。

那以上这些,就是为什么要有这3个非常重要的指标的原因。

好,那下一节课中,我们要来看看关于precitionrecall的一个矩阵,这个矩阵呢,将会是我们工作中分析结果常用的。

P r e c i s i o n = t p t p + f p R e c a l l = t p t p + f n \begin{align*} Precision & = \frac{tp}{ tp + fp} \\ Recall & = \frac{tp}{tp + fn} \end{align*} PrecisionRecall=tp+fptp=tp+fntp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/165576.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jvm 各个版本支持的参数

知道一些 jvm 调优参数,但是没有找到官网对应的文档,在网上的一些文章偶然发现,记录一下。 https://docs.oracle.com/en/java/javase/ 包含各个版本 jdk 8 分为 windows 和 unix 系统 https://docs.oracle.com/javase/8/docs/technotes/too…

【ChatGLM2-6B】nginx转发配置

背景 好不容易把ChatGLM2-6B大语言模型部署好了,使用streamlit方式启动起来了,终于可以愉快的玩耍了,然后想着申请一个域名,使用HTTPS协议访问,但实践过程中,发现这个大语言模型的nginx转发配置还是有点小…

STM32F4x之中断一

一、中断简介 中断概念:程序在运行过程中发生了外部或内部事件时,导致中断了正在执行的程序,让CPU转到外部或内部事件中去执行。 中断的作用:大量节约CPU资源,提高程序的效率,即避免重要事件被错过。 中断…

利用TypeScript 和 jsdom 库实现自动化抓取数据

以下是一个使用 TypeScript 和 jsdom 库的下载器程序,用于下载zhihu的内容。此程序使用了 duoip.cn/get_proxy 这段代码。 import { JSDOM } from jsdom; import { getProxy } from https://www.duoip.cn/get_proxy;const zhihuUrl https://www.zhihu.com;(async (…

NFT Insider112:The Sandbox聘请Apple高管担任其首席内容官,YGG 将在菲律宾举办Web3游戏峰会

引言:NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品,浓缩每周NFT新闻,为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据,艺术新闻类,游戏新闻类,虚拟世界类&#…

Qt扫盲-QTextCodec理论总结

QTextCodec理论总结 一、概述二、编码支持三、使用四、创建自己的编解码器类 一、概述 QTextCodec 是Qt提供的一个管理字符串编码的功能,他可以在不同编码方式中来回转换,在文件读取的时候、格式编码转换的时候用处很大。Qt使用Unicode 编码来存储、绘制…

Aocoda-RC F405V2 FC(STM32F405RGT6 v.s. AT32F435RGT7) IO Definitions

[TOC](Aocoda-RC F405V2 FC(STM32F405RGT6 v.s. AT32F435RGT7) IO Definitions) 1. 源由 Aocoda-RC F405V2飞控支持betaflight/inav/Ardupilot固件,是一款固件兼容性非常不错的开源硬件。 之前我们对比过STM32F405RGT6 v.s. AT32F435RGT7 Comparison for Flight …

java中的容器(集合),HashMap底层原理,ArrayList、LinkedList、Vector区别,hashMap加载因子0.75原因

一、java中的容器 集合主要分为Collection和Map两大接口;Collection集合的子接口有List、Set;List集合的实现类有ArrayList底层是数组、LinkedList底层是双向非循环列表、Vector;Set集合的实现类有HashSet、TreeSet;Map集合的实现…

freeipa server副本同步中断,两主节点数据不一致

/var/log/messages 和/var/log/dirsrv/slapd-testhadoop-COM 日志都出现以下日志: If replication stops, the consumer may need to be reinitialized. [27/Jun/2023:05:15:09.469361922 0800] - ERR - NSMMReplicationPlugin - changelog program - repl_plugin_name_cl - a…

使用Axure RP和内网穿透技术制作静态站点并实现公网访问

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

某全球领先的芯片供应商:优化数据跨网交换流程,提高安全管控能力

1、客户介绍 某全球领先的芯片供应商,成立于2005年,总部设于北京,在国内上海、深圳、合肥等地及国外多个国家和地区均设有分支机构和办事处,致力于为客户提供更优质、便捷的服务。 2、建设背景 该公司基于网络安全管理的需求&am…

PCA降维可视化

二维 import pandas as pd import warnings warnings.filterwarnings("ignore")df pd.read_csv(data/data.csv).dropna() features df.columns[:-1] X, y df[features], df[label]from sklearn.preprocessing import MinMaxScaler # 创建MinMaxScaler对象 scaler…

接口测试 Jmeter 接口测试 —— 请求 Headers 与传参方式

一、 背景: 在使用 Jmeter 进行接口测试时,有些小伙伴不知道 Headers 和请求参数 (Parameters,Body Data) 的联系,本文主要讲 Content-Type 为 application/x-www-form-urlencoded 和 application/json 的场景。 1、使用 Parame…

【ROS 2 基础-常用工具】-7 Rviz仿真机器人

所有内容请查看:博客学习目录_Howe_xixi的博客-CSDN博客

OpenLDAP LDIF详解

手把手一步步搭建LDAP服务器并加域 有必要理解的概念LDAPWindows Active Directory 服务器配置安装 OpenLDAP自定义安装修改对象(用户和分组等)修改olcSuffix 和 olcRootDN 属性增加olcRootPW 属性修改olcAccess属性验证新属性值 添加对象(用…

线性代数-Python-01:向量的基本运算 - 手写Vector及numpy的基本用法

文章目录 一、代码仓库二、向量的基本运算2.1 加法2.2 数量乘法2.3 向量运算的基本性质2.4 零向量2.5 向量的长度2.6 单位向量2.7 点乘/内积:两个向量的乘法 --答案是一个标量 三、手写Vector代码3.1 在控制台测试__repr__和__str__方法3.2 创建实例测试代码3.3 完整…

sql中的group by 举例子数据库日期带汉字转换2023年10月18天

sql中的group by 举例子 sql中 group by多个字段,对所有字段做group by_group by 多个字段_Foools的博客-CSDN博客 【精选】玩转SQL语句之group by 多字段分组查询与having子句,一篇解决你的疑惑!_sql多个分组查询-CSDN博客 select to_char…

【PACS系统源码】与医院HIS系统双向数据交换,实现医学影像集成与影像后处理功能

​医院医学影像PACS系统源码,集成三维影像后处理功能,包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等功能。系统功能强大,代码完整。 PACS系统与医院HIS实现双向数据交换&#xff0c…

语音芯片KT142C两种音频输出方式PWM和DAC的区别

目录 语音芯片KT142C两种音频输出方式PWM和DAC的区别 一般的语音芯片,输出方式,无外乎两种,即dac输出,或者PWM输出 其中dac的输出,一般应用场景都是外挂功放芯片,实现声音的放大,比如常用的音箱…

【常用图像增强技术,Python-opencv】

文章目录 常用图像增强技术调整大小灰度变换标准化随机旋转中心剪切随机裁剪高斯模糊亮度、对比度和饱和度调节水平翻转垂直翻转高斯噪声随机块中心区域 常用图像增强技术 图像增强技术是常用于数据增强的方法,可以帮助增加数据集中图像的多样性,提高深…