首页
友情链接
点点滴滴
关于本站
秋码记录
一个游离于山间之上的Java爱好者 | A Java lover living in the mountains
累计撰写
152
篇文章
累计创建
336
个标签
累计创建
47
个分类
栏目
首页
友情链接
点点滴滴
关于本站
搜索
腾讯云COS托管静态网站,以及如何解决访问出现了下载网页的情况
腾讯云对象存储(Cloud Object Storage,简称COS),与其他云厂商所提供的云对象存储都是面向非结构化数据,只是每个云厂商的叫法有别于他家,或许是更能彰显厂商的品牌吧! 但不管云厂商怎么给云对象存储起名,最终客户关心的还是性价比。 使用云对象存储,无非是存放些静态资源(javascript 第三方库、项目中内部的javascript文件、样式文件css、字体文件、小图标等),以此来减轻服务器所承载的压力,从而使得整个站点让用户体验效果显著提升了。 然而,本文要讲的是,怎么样在云对象存储中托管静态网站(这虽然听起来有点可笑,这年头,谁还玩静态网站啊。你也别笑,秋码记录 就是一个很好的静态网站的例子,它也的确是静态网站,可它却具有了与用户交流的文章评论`功能!) 当然咯,云对象存储用来托管静态网站,也只是在开发、测试阶段,毕竟大流量的情况下,费用那是不可估量的! 创建存储捅 对于存储捅这个名词,刚刚说了,每个云厂商的叫法不同而已。 首先,进入腾讯云-》控制台(在这之前,你当然得购买了腾讯云 COS),创建存储捅,名称随便填写,在访问权限选择公共读私有写。 而后,服务端加密这一项,选择SSE-COS(看着名称,估计是腾讯云又仿造他人什么的吧!) 就这样,腾讯云COS就创建成功了,之后便可以上传你的静态资源到这个对象捅里了。 配置静态网站 既然,我们使用COS来托管静态网站,那么是少不了些必要的配置,比如开启静态网站`开关等等。 在左侧导航栏中找到基础配置,随后在其子项的静态网站开启静态网站的配置。(感觉在绕口令似的,其实,不关你是这么觉,我也这么觉得。) 绑定自定义域名 同样的,还是在左侧导航栏,找到域名与传输管理这一泪目,点开它底下的自项,点击自定义绑定域名。 在绑定自定义域名之前,你得先确认你刚购买的COS区域是国内的,还是非国内的,若是国内区域的COS,那么你绑定自定义域名时,这个自定义域名是需要备案的。当然咯,COS购买时选择的是香港区域,自定义域名是不需要备案的哦! 浏览器访问托管的静态网站却下载了文件 很不辛,在你配置了存储捅的静态网站,上传了所有的静态资源后,兴致勃勃地打开浏览器,你以为页面能够如期的展示你所希望的样子,然而,历史性的一刻,让你瞬间愕然,这是怎么回事呢?怎么就直接下载了页面文件(也就是下载当前的index.html`文件)?这到底是哪个环节出了问题? 然而,你是按着官方文档来着,并且文档上也是这么做的,中间也没有遗漏些什么重要配置啊!(关键是也没什么重要配置,充其量就是开启了静态网站的开关)。 于是,你借助搜索引擎的强大搜寻功能,找找看,到底有没有解决办法(也就是别人在COS托管静态网站时,对于访问时出现下载文件`是怎么处理的)。 不搜不知道,一搜可谓是天下知。使用COS(也有其他云厂商的)托管静态网站的博文、帖子、论坛还真不少,你点开一看,他们与你的静态网站配置如出一辙,他们也同样出现了你所出现的问题(没把你绕进去吧,也就是他们跟你一样,在浏览器访问也出现了下载index.html文件。) 最终,解决办法便是在刚刚上传的index.html,点击右上角的...,在上弹出的列表项中,再次点击自定义头部 当你看到这个对话框,你或许就该恍然大悟了,也总算明白了,为什么浏览器访问会出现下载 index.html的情况了吧!毕竟,腾讯云默认将你上传的文件头部定义为text/html。 我们点击编辑来修改这个index.html文件表头。 在参数选择下拉框中选中Content-Disposition,值是手动输入inline. 现在,你再次打开浏览器进行访问,这回,展现在你眼前的,便是你所期望的页面展示了。 可当你回过头,再去查看index.html头部信息时,却发现它自动的加上初始的那个Header信息,这时,你不禁啐了一口,“腾讯云,真TMD恶心,哦!不,国内的这些云厂商都TMD超恶心”。 当然咯,不管是腾讯云COS,还是其他国内云厂商,想要使用云对象存储来托管静态网站还是比较,怎么说呢!用来开发、测试勉强还凑合吧!
2024-07-19
[云计算]
错误分析 (Machine Learning 研习十九)
错误分析 您将探索数据准备选项,尝试多个模型,筛选出最佳模型,使用 Grid SearchCV微调其超参数,并尽可能实现自动化。在此,我们假设您已经找到了一个有前途的模型,并希望找到改进它的方法。其中一种方法就是分析它所犯的错误类型。 首先,查看混淆矩阵。为此,首先需要使用 cross_val_predict() 函数进行预测;然后可以像之前一样,将标签和预测值传递给 confusion_matrix()函数。不过,由于现在有 10 个类别而不是 2 个,混淆矩阵将包含大量数字,可能难以读取。 混淆矩阵的彩色图更容易分析。要绘制这样的图表,请使用ConfusionMatrixDisplay.from_predictions() 函数,如下所示: from sklearn.metrics import ConfusionMatrixDisplay y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3) ConfusionMatrixDisplay.from_predictions(y_train, y_train_pred) plt.show() 这就产生了 图1 中的左图。这个混淆矩阵看起来相当不错:大多数图像都在主对角线上,这意味着它们被正确分类了。请注意,对角线上第 5 行第 5 列的单元格看起来比其他数字略暗。这可能是因为模型对 5 的错误较多,也可能是因为数据集中 5 的数量比其他数字少。这就是为什么要对混淆矩阵进行归一化处理,将每个值除以相应(真实)类别中的图像总数(即除以行的总和)。只需设置 normalize="true "即可。我们还可以指定 val ues_format=".0%"参数来显示不带小数点的百分比。下面的代码将生成 图1 右侧的图表: ConfusionMatrixDisplay.from_predictions(y_train, y_train_pred, normalize="true", values_format=".0%") plt.show() 现在我们不难发现,只有 82% 的 5 图像被正确分类。模型在处理 5 的图像时最常见的错误是将其误判为 8:在所有 5 的图像中,有 10%的图像被误判为 8。但只有 2% 的 8 被误判为 5;混淆矩阵通常不是对称的!如果你仔细观察,就会发现很多数字都被错误地分类为 8,但从这张图上并不能一眼看出。如果想让错误更明显,可以尝试将正确预测的权重设为零。下面的代码就是这样做的,并生成了图2 左侧的图表: sample_weight = (y_train_pred !
2024-04-10
[Machine Learning 人工智能]
多类别分类器(Machine Learning 研习十八)
多类别分类器 二元分类器可以区分两个类别,而多类别分类器(也称为多叉分类器)可以区分两个以上的类别。 一些 Scikit-Learn 分类器(如 LogisticRegression、RandomForestClassifier 和 GaussianNB)能够原生处理多个类别。其他分类器则是严格的二进制分类器(如 SGDClassifier 和 SVC)。不过,您可以使用多种策略来使用多个二进制分类器执行多类分类。 要创建一个能将数字图像分为 10 类(从 0 到 9)的系统,一种方法是训练 10 个二进制分类器,每个数字一个(0-检测器、1-检测器、2-检测器,以此类推)。然后,当您想对一幅图像进行分类时,您可以从每个分类器中得到该图像的判定分数,然后选择分类器输出分数最高的类别。这就是所谓的 “以一敌百”(OvR)策略,有时也称为 “以一敌众”(OvA)策略。 另一种策略是为每一对数字训练一个二元分类器:一个用于区分 0 和 1,另一个用于区分 0 和 2,还有一个用于区分 1 和 2,以此类推。这就是所谓的一对一(OvO)策略。如果有 N 个类别,则需要训练 N × (N - 1) / 2 个分类器。对于 MNIST 问题,这意味着要训练 45 个二进制分类器!当你想对一幅图像进行分类时,你必须让图像通过所有 45 个分类器,看看哪个分类器赢得了最多的对决。OvO 的主要优势在于,每个分类器只需在训练集中包含其必须区分的两个类别的部分进行训练。 有些算法(如支持向量机分类器)随训练集的大小而缩放,效果不佳。对于这些算法,OvO 是首选,因为在小训练集上训练多个分类器比在大训练集上训练少数分类器更快。不过,对于大多数二元分类算法来说,OvR 是首选。 Scikit-Learn 会检测你是否尝试在多分类任务中使用二元分类算法,并根据算法自动运行 OvR 或 OvO。让我们使用 sklearn.svm.SVC 类支持向量机分类器来尝试一下。我们只对前 2,000 张图像进行训练,否则会耗费很长时间: from sklearn.svm import SVC svm_clf = SVC(random_state=42) svm_clf.fit(X_train[:2000], y_train[:2000]) # y_train, not y_train_5 我们使用从 0 到 9 的原始目标类别(y_train),而不是 5 对其余目标类别(y_train_5)来训练 SVC。由于有 10 个类别(即多于 2 个),Scikit-Learn 使用 OvO 策略训练了 45 个二元分类器。现在,让我们对一幅图像进行预测:
2024-04-03
[Machine Learning 人工智能]
使用CSS计数器,在目录名称前加上了序号,让目录看起来更加井然有序
目录(Text of Contents缩写为TOC),其实就是一篇文章的概要或简述。这好比,去书店买书,先是被这本书的标题所吸引,而后我们才会,翻开这本书目录,看看这本书主要是在讲些什么?我们在看目录的同时,脑中也在不停的思衬,”这本书到底值不值得买呢?但是没有什么实战内容耶!“ 文章目录 其实,一篇文章也不非要目录的,只要段落分的好,就算是长篇大论也是无关紧要的! 只是文章有了目录,让人一眼就能瞧出这篇文章到底讲了什么?虽然标题上有说,但还是得为哪几个段落起个副标题。 再说了,文章目录可以让用户在页面上,点击到达指定目录名称下进行浏览。虽然这在很大层度上是可以通过鼠标滑动,滚动到想要浏览的位置。 Hugo-theme-kiwi开源博客主题已然有了文章目录这一功能,也就是 秋码记录 站点正在使用的博客主题(由于 秋码记录 托管于 Github.com Pages,故而国内的友人在访问时,比较缓慢,甚至有时可能出现无法打开该网站)。 对目录名称前添加序号,我们首先想到的当然是使用Hugo模板渲染去实现。 序号,顾名思义,就是有顺序的号码,通俗来讲,便是1、,2、,3、,4、,……。可在Hugo模板渲染中使用计数器来实现。 css计数器 或许也只有在使用了CSS 计数器后,你就会摒弃代码中使用Hugo模板渲染的那部分又长又拖代码了。 在CSS计数器中,counter-reset和counter-increment属性是必不可少的。counter-reset在每次新的列表开始时重置计数器,而counter-increment在每个列表项上增加计数器。 需要注意的是:counter-reset 是需要计数的父标签上的! 那么,就将 counter-reset设置在ol标签上即可,即便是某一项有子目录,那也还是在ol标签内的! .toc-content ol{ list-style-type: none; counter-reset: item } 现在,我们就可以对目录名称设置伪选择器了。 在编写CSS样式之前,有必要说下counters()函数,在CSS中,它返回一个计数器的列表值,这个列表可以包含一个或者多个嵌套的计数器。 函数counters()有两个参数: 第一个参数是你要访问的计数器的名称,在你的例子中,该名称就是 item。 第二个参数是字符串,用来分隔计数器的各个级别。在你的例子中,这个分隔符是英文的句点 . .toc-content ol li a:first-of-type::before{ counter-increment: item; content: counters(item,".")"、"; font-weight: 700; margin-right: 1px; } 比如在多级嵌套的列表中,如果在第一级的第二个项中的第三个小项,那么 counters() 的值就会是 2.3、。 字符串、 紧接着 counters(item, ".") 的作用是将结果后面添加一个顿号,使其格式化输出更美观。 所以 counters(item, ".") ". " 的作用就是生成并显示一个根据当前嵌套列表项的层级和序号构成的数字序列,每一级数字之间用句点分隔,并在最后跟着一个顿号。例如输出1、,2.1、,2.2、,等等。 最终效果可查看秋码记录文章详情页,右侧侧边栏目录。
2024-04-01
[前端]
使用 golang 以及 Gin 框架,将上传的图片在不保存至本地的情况下添加水印,并上传至阿里云 OSS
正如标题所述,使用golang对上传图片添加水印,以及将图片上传到阿里云OSS,网上一搜索,便有你想要的结果了,可是,他们却先将上传图片添加水印后保存在本地,而后再将添加了水印的图片上传到阿里云OSS。 这无疑是暂时占用了你电脑的磁盘空间(这里说是暂时,因为你可以通过程序对上传到阿里云OSS成功的图片进行删除),即便是这样,它也是消耗了磁盘读写操作,虽然人类是察觉不到这么细微的变化。 然而,作为技术人员的我们(不介意我这么称呼自己吧!),使能够Review出这段程序的问题。很显然,本地图片是要通过程序处理,添加水印,而后最终储存到阿里云OSS中,而不是又要在本地多存了一张比原图多了些水印的图片。 图像处理库 既然我们的目的明确了,那么就卷起柚子加油干吧! 虽然,使用golang对上传图片添加水印,以及如何将图片上传到阿里云OSS中,是两个独立分开的。但是,这两步看似分而食之的程序,其实是可以合二为一的!(我想,正在浏览本文的你,也是这么想的!) 这是可行的方案,毕竟先前的秋码记录 就是这么做的(那是使用Java构建的那些年!当然现在的 秋码记录 改用 ```Hugo·``搭建了)。 既然,java能实现对上传图片添加水印,而不暂时保存在本地,立马即可上传到阿里云OSS中。想必,golang也是可以完成的! 然而,网上相关的资料有限,才能铸就本文的诞生! 首先,我是用golang的版本是1.19,虽然不是最新的,但却不妨碍我们继续对本文的讲解。 虽然,人类总是对新鲜事物充满好奇,从而萌生了猎奇心。但也只有在旧事物的烘衬下,人们才能对新事物寄以最大的希望!这就好比,老婆总是别人的好看(当然,别人的老婆也有没有自己老婆好看的),这才造就了黄脸婆这一全国男人在没有老婆在身旁统一叹息声! 你得在你电脑任一磁盘下,新建一空文件夹,随后打开黑窗口(Terminal),输入以下命令,说明是modules进行管理的(毕竟我使用的是golang 1.19): go mod init qiucode.cn/uploadImage 对于以上这行命令,就是初始化golang模块(module),在golang的世界是```万物皆可模块``(我说的如果不对,那么说出你的想法)。 初始化项目后,我们会发现文件夹下多了个go.mod文件(这个就是用来管理第三方依赖库的管理文件,不需要操作!),在该同级目录下新建main.go文件。 既然本文是探讨如何实现图片添加水印的,那么引入图像库那是必不可少的! go get github.com/fogleman/gg 本文不会对这个图像库进行深层次的讲解!毕竟本文的核心内容是介绍如何对图片添加水印,而不是避重就轻、本末倒置讲起了本该一笔带过的东西,却花了浓墨重彩去着重的描绘刻画它,到头来,却失了初心,乱了本文的主旨,实属不该。(实在不清楚的,可以去查看其文档) 很显然,将图片上传到阿里云OSS上,引入其SDK,那是必不可少的(关于这一点,应该不需要我多费口舌了吧) go get github.com/aliyun/aliyun-oss-go-sdk/oss 接下来的这个依赖库,并不是必须的(那就是可选的),毕竟,有它没有它,本文都可以实现! go get github.com/gin-gonic/gin 是啊!都说了,不引入它,本文也可以实现,那么我为什么还引入了呢?(关于这一点,欢迎你能在评论中留下你的只言片语,请不要吝啬你的文字!) 用代码实现标题的需求 前提准备工作就绪,我们该正式进入编码环节了。到了这里,正处于屏幕前的你,想必早就迫不及待了吧!毕竟,你就是与我有同样的需求,才会浏览本文的(当然也有那种,鼠标不小心点到了,但那种几率是很小的,我相信你不是属于那一类的) 首先,我们使用VS Code(你也可以使用其他你平时常用的IDE,不必非要使用与我一样的VS Code,然而,作为一款开源免费的IDE,你还有什么理由不去使用它呢?哦,差点忘记了,都说了,使用IDE是个人的自由,可我这么一说,倒有了让你使用VS Code之嫌。虽然,或许你比较喜欢使用收费软件,但你都是找的破解方法来破解软件,从而使用它们) 打开刚刚新建的main.go文件,开始逐步实现标题的需求。 package main import ( "bytes" "image" "image/png" // "image/jepg" //用于对 jpg 格式的图片进行处理 本文暂时不对 jpg 图片做处理 "github.com/gin-gonic/gin" //web 框架 "github.com/fogleman/gg" // 图像处理哭 "github.com/aliyun/aliyun-oss-go-sdk/oss" //阿里云OSS SDK ) 随后,我们在main函数中实现标题中的需求。
2024-03-30
[golang gin]
绘制特征曲线-ROC(Machine Learning 研习十七)
接收者操作特征曲线(ROC)是二元分类器的另一个常用工具。它与精确度/召回率曲线非常相似,但 ROC 曲线不是绘制精确度与召回率的关系曲线,而是绘制真阳性率(召回率的另一个名称)与假阳性率(FPR)的关系曲线。FPR(也称 “下降率”)是阴性实例被错误归类为阳性实例的比率。它等于 1 - 真阴性率 (TNR),即正确分类为阴性的阴性实例的比率。TNR 也称为特异性。因此,ROC 曲线是灵敏度(召回率)与 1 - 特异性的关系图 要绘制 ROC 曲线,首先要使用 roc_curve() 函数计算不同阈值的 TPR 和 FPR: from sklearn.metrics import roc_curve fpr, tpr, thresholds = roc_curve(y_train_5, y_scores) 然后可以使用 Matplotlib 绘制 FPR 与 TPR 的对比图。下面的代码可以绘制出 见下图 所示的图形。要找到与 90% 精度相对应的点,我们需要查找所需阈值的索引。由于在这种情况下阈值是按递减顺序排列的,因此我们在第一行使用 <= 而不是 >=: idx_for_threshold_at_90 = (thresholds <= threshold_for_90_precision).argmax() tpr_90, fpr_90 = tpr[idx_for_threshold_at_90], fpr[idx_for_threshold_at_90] plt.plot(fpr, tpr, linewidth=2, label="ROC curve") plt.plot([0, 1], [0, 1], 'k:', label="Random classifier's ROC curve") plt.plot([fpr_90], [tpr_90], "ko", label="Threshold for 90% precision") [.
2024-03-29
[Machine Learning 人工智能]
网站引入 Prism,使得代码高亮显示,并一键复制代码块
曾几何时,苦恼如何将本地写好的博文,更好的展示读者屏幕前?若只是简简单单的文章,其实还是很好的解决它的!可是,像我们这样写技术文章(有点牵强)的,在文章内容嵌入部分代码是在所难免的。 然而,由于没能将代码与文本区分开来,致使两者混在一起,分不出彼此。由此给读者带来了视觉上得不适,它并没有很好的像代码编辑器那样高亮。 下载 Prism 虽然市面上能让代码块高亮显示,远不止Prism这一款,而我又为什么选择这一款呢?这的确是个好问题,然而我只能回答您的是,它功能比较强大吧!(或许您还不能信服),这就好比是情人眼里出西施,您的老婆/老公或女朋友/男朋友长得不是那么美/那么帅(或许您在某一瞬间也是这么觉得),但是,您不还是选择了她/他吗?即便是,您和伴侣在逛街时,迎面走来一位身材高挑的美女/帅哥,想必您的伴侣是在您不经意间,偷瞄了一眼。 进入prism官网下载: https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript 随后,我们在项目中引入Prism.css样式文件。 <link href="themes/prism.css" rel="stylesheet" /> 以及Prism.js文件。 <script src="prism.js"></script> 当然咯,您的代码块是需要使用<pre>和<code class="language-*"标签。 <pre><code class="language-html"> <link href="themes/prism.css" rel="stylesheet" /> </code></pre> 添加 clipboard 复制代码按钮 若是有一点按钮就可以复制这段代码,想必应该是没有人会再去用鼠标去滑动选择代码,然后右键,选择复制选项,或者直接按住键盘上的Ctrl + C。 首先,想要在项目中添加clipboard功能,那么,就显得下载它,这是毋庸置疑的! 当然,我们还是到Prism官网下载它, 在项目中引入: <script src="plugins/clipboard.js"></script> Hugo-theme-kiwi 中引入 Prism 首先,我们在Hugo-theme-kiwi主题的head.html文件引入blackmac.css样式文件。 <link rel="stylesheet" href="{{ .Site.BaseURL }}css/blackmac.css"> blackmac.css文件内容如下: code[class*="language-"],pre[class*="language-"]{color:#f8f8f2;background:#313238;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:2;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;}pre[class*="language-"]{padding:.5em;margin:.5em 0;overflow:auto;}:not(pre)>code[class*="language-"],pre[class*="language-"]{background:#21252a}:not(pre)>code[class*="language-"]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999;}.token.punctuation{color:#ccc;}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#e2777a;}.token.function-name{color:#6196cc;}.token.boolean,.token.number,.token.function{color:#f08d49;}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555;}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd;}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699;}.token.operator,.token.entity,.token.url{color:#67cdcc;}.token.important,.token.bold{font-weight:bold;}.token.italic{font-style:italic;}.token.entity{cursor:help;}.token.inserted{color:green;}pre.line-numbers{padding-bottom:.8em;padding-left:3.3em;counter-reset:linenumber}pre.line-numbers>code{white-space:inherit font-size:15px}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:3em;font-size:100%;left:-0.1em;width:3em;letter-spacing:-1px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.9em;text-align:right;background:#272c33}div.code-toolbar{font-size:100%;border-radius:4px;position:relative;box-shadow:0 0 20px 5px rgba(0,0,0,.4);padding-top:30px;background-color:#161616;margin:20px 0 20px 0}.code-toolbar:before{content:" ";position:absolute;-webkit-border-radius:50%;border-radius:50%;background:#fc625d;width:11px;height:11px;left:10px;top:10px;-webkit-box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;z-index:2}div.code-toolbar>.toolbar{padding-right:.4em;position:absolute;top:.09em;right:.2em;width:100%;text-align:center;}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar>.toolbar .
2024-03-23
[前端]
精确率(召回率)的权衡(Machine Learning 研习十六)
精确率(召回率)的权衡 为了理解这种权衡,让我们看看 SGDClassifier 如何做出分类决策。 对于每个实例,它根据决策函数计算分数。 如果该分数大于阈值,则将该实例分配给正类; 否则它会将其分配给负类。 图 3-4 显示了从左侧最低分数到右侧最高分数的几个数字。 假设决策阈值位于中心箭头(两个 5 之间):您会在该阈值右侧发现 4 个真阳性(实际为 5),以及 1 个假阳性(实际上为 6)。 因此,使用该阈值,精度为 80%(5 分之 4)。 但在 6 个实际的 5 中,分类器仅检测到 4 个,因此召回率为 67%(6 中的 4)。 如果提高阈值(将其移动到右侧的箭头),假阳性(6)会变成真阴性,从而提高精度(在本例中高达 100%),但一个真阳性会变成假阴性 ,将召回率降低至 50%。 相反,降低阈值会增加召回率并降低精确度。 Scikit-Learn 不允许您直接设置阈值,但它允许您访问它用于进行预测的决策分数。 您可以调用其decision_function()方法,而不是调用分类器的predict()方法,该方法返回每个实例的分数,然后使用您想要根据这些分数进行预测的任何阈值: SGDClassifier 使用等于 0 的阈值,因此前面的代码返回与 Predict() 方法相同的结果(即 True)。 让我们提高门槛: 这证实了提高阈值会降低召回率。 该图像实际上代表的是 5,当阈值为 0 时分类器会检测到它,但当阈值增加到 3,000 时分类器会错过它。 y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function") 有了这些分数,使用 precision_recall_curve() 函数计算所有可能阈值的精度和召回率(该函数添加最后精度 0 和最后召回率 1,对应于无限阈值): from sklearn.
2024-03-21
[Machine Learning 人工智能]
对模型性能进行评估(Machine Learning 研习十五)
在上一篇我们已然训练了一个用于对数字图像识别的模型,但我们目前还不知道该模型在识别数字图像效率如何?所以,本文将对该模型进行评估。 使用交叉验证衡量准确性 评估模型的一个好方法是使用交叉验证,让我们使用cross_val_score()函数来评估我们的 SGDClassifier 模型,使用三折的 k 折交叉验证。k-fold 交叉验证意味着将训练集分成 k 个折叠(在本例中是三个),然后训练模型 k 次,每次取出一个不同的折叠进行评估: 当您看到这组数字,是不是感到很兴奋?毕竟所有交叉验证折叠的准确率(预测准确率)均超过了 95%。然而,在您兴奋于这组数字前,还是让我们来看看一个假分类器,它只是将每张图片归入最常见的类别,在本例中就是负类别(即非 5): from sklearn.dummy import DummyClassifier dummy_clf = DummyClassifier() dummy_clf.fit(X_train, y_train_5) print(any(dummy_clf.predict(X_train))) # prints False: no 5s detected 您能猜出这个模型的准确度吗?让我们一探究竟: 没错,它的准确率超过 90%!这只是因为只有大约 10% 的图片是 5,所以如果你总是猜测图片不是 5,你就会有大约 90% 的时间是正确的。比诺斯特拉达穆斯还准。 这说明了为什么准确率通常不是分类器的首选性能指标,尤其是在处理偏斜 数据集时(即某些类别的出现频率远高于其他类别)。评估分类器性能的更好方法是查看混淆矩阵(CM)。 实施交叉验证 与 Scikit-Learn 现成提供的功能相比,您有时需要对交叉验证过程进行更多控制。在这种情况下,你可以自己实现交叉验证。下面的代码与 Scikit-Learn 的 cross_val_score() 函数做了大致相同的事情,并会打印出相同的结果: from sklearn.model_selection import StratifiedKFold from sklearn.base import clone skfolds = StratifiedKFold(n_splits=3) # add shuffle=True if the dataset is # not already shuffled for train_index, test_index in skfolds.
2024-03-15
[Machine Learning 人工智能]
图像识别之入门案例之数字识别(Machine Learning 研习十四)
在前面的文章中,我们曾提到最为常见的监督学习任务是回归(预测价值)和分类(预测类别)。我们使用线性回归、决策树和随机森林等各种算法探讨了回归任务,即预测房屋价值。现在,我们将把注意力转向分类系统。 MNIST数据集 我们将使用 MNIST 数据集,这是一组由人类手写的 70,000 张小数字图像。每张图片都标注了所代表的数字。人们对这个数据集的研究非常深入,以至于它经常被称为机器学习的 “hello world”:每当人们提出一种新的分类算法时,他们都会好奇地想看看这种算法在 MNIST 上的表现如何,而且任何学习机器学习的人迟早都会用到这个数据集。 Scikit-Learn 提供了许多下载流行数据集的辅助函数。MNIST 就是其中之一。以下代码从 OpenML.org 获取 MNIST 数据集: from sklearn.datasets import fetch_openml mnist = fetch_openml('mnist_784', as_frame=False) sklearn.datasets 包主要包含三种类型的函数:fetch_* 函数(如 fetch_openml())用于下载现实生活中的数据集;load_* 函数用于加载 Scikit-Learn捆绑的小型玩具数据集(因此无需通过互联网下载);make_* 函数用于生成假数据集,对测试非常有用。生成的数据集通常以 (X, y) 元组的形式返回,其中包含输入数据和目标数据,两者都是 NumPy 数组。其他数据集以 sklearn.utils.Bunch 对象的形式返回,这是一个字典,其条目也可以作为属性访问。它们通常包含以下条目: “DESCR” 数据集描述 “data” 输入数据,通常为Numpy二维数组 “target” 标签,通常为Numpy一维数组 fetch_openml() 函数有点不寻常,因为默认情况下,它以 Pandas DataFrame 的形式返回输入,以 Pandas Series 的形式返回标签(除非数据集很稀疏)。但 MNIST 数据集包含图像,而 DataFrame 并不适合图像,因此最好设置 as_frame=False,以 NumPy 数组的形式获取数据。让我们来看看这些数组: 共有 70,000 幅图像,每幅图像有 784 个特征。这是因为每幅图像都是 28 × 28 像素,每个特征只代表一个像素的强度,从 0(白色)到 255(黑色)。让我们来看看数据集中的一个数字(图 3-1)。我们需要做的就是抓取一个实例的特征向量,将其重塑为 28 × 28 数组,然后使用 Matplotlib 的 imshow() 函数显示出来。我们使用 cmap="binary" 来获取灰度颜色图,其中 0 代表白色,255 代表黑色:
2024-03-15
[Machine Learning 人工智能]
微调模型——续(Machine Learning 研习之十三)
集成方法 微调系统的另一种方法是尝试组合性能最佳的模型。 群体(或“整体”)通常会比最好的单个模型表现得更好,就像随机森林比它们所依赖的单个决策树表现更好一样,特别是当各个模型犯下不同类型的错误时。 例如,您可以训练和微调 k 最近邻模型,然后创建一个仅预测随机森林预测和该模型预测的平均值的集成模型。 分析最佳模型及其错误 通过检查最佳模型,您通常会获得对问题的深入见解。 例如,RandomForestRegressor可以指示每个属性对于做出准确预测的相对重要性: 让我们按降序对这些重要性分数进行排序,并将它们显示在相应的属性名称旁边: 有了这些信息,您可能想尝试删除一些不太有用的功能(例如,显然只有一个ocean_proximity类别真正有用,因此您可以尝试删除其他功能)。 您还应该查看系统所犯的具体错误,然后尝试了解为什么会犯这些错误,以及如何解决问题:添加额外的功能或删除无信息的功能,清理异常值等。 现在也是一个好时机,可以确保您的模型不仅平均运行良好,而且适用于所有类别的地区,无论是农村还是城市、富裕还是贫穷、北部还是南部、少数民族还是非少数民族等。 每个类别的验证集需要一些工作,但这很重要:如果您的模型在整个地区类别上表现不佳,那么在问题解决之前可能不应该部署它,或者至少不应该使用它 对该类别进行预测,因为它可能弊大于利。 在测试集上评估您的系统 对模型进行一段时间的调整后,您最终会得到一个性能足够好的系统。 您已准备好在测试集上评估最终模型。 这个过程没有什么特别的; 只需从测试集中获取预测变量和标签并运行Final_model来转换数据并进行预测,然后评估这些预测: X_test = strat_test_set.drop("median_house_value", axis=1) y_test = strat_test_set["median_house_value"].copy() final_predictions = final_model.predict(X_test) final_rmse = mean_squared_error(y_test, final_predictions, squared=False) print(final_rmse) # prints 41424.40026462184 在某些情况下,这样的泛化误差点估计不足以说服您启动:如果它只比当前生产的模型好 0.1% 怎么办? 您可能想了解这个估计的精确度。 为此,您可以使用 scipy.stats.t.interval() 计算泛化误差的 95% 置信区间。 您会得到从 39,275 到 43,467 的相当大的区间,而您之前的点估计值 41,424 大致位于中间: 如果您进行了大量的超参数调整,性能通常会比使用交叉验证测量的性能稍差。 这是因为您的系统最终经过微调以在验证数据上表现良好,但在未知数据集上可能表现不佳。 本示例中的情况并非如此,因为测试 RMSE低于验证 RMSE,但当发生这种情况时,您必须抵制调整超参数以使数字在测试集上看起来不错的诱惑; 这些改进不太可能推广到新数据。 现在是项目预启动阶段:您需要展示您的解决方案(突出显示您所学到的内容、有效的内容和无效的内容、做出的假设以及系统的局限性),记录所有内容,并使用以下内容创建精美的演示文稿: 清晰的可视化和易于记忆的陈述(例如,“收入中位数是房价的第一预测指标”)。 在这个加州住房示例中,系统的最终性能并不比专家的价格估计好多少,专家的价格估计通常会下降 30%,但启动它可能仍然是一个好主意,特别是如果这样可以释放更多资金 给专家一些时间,以便他们可以从事更有趣、更有成效的任务。 启动、监控和维护您的系统 您现在需要准备好用于生产的解决方案(例如,完善代码、编写文档和测试等)。 然后您可以将模型部署到生产环境。 最基本的方法就是保存您训练的最佳模型,将文件传输到您的生产环境并加载它。 要保存模型,您可以使用 joblib 库,如下所示:
2024-03-09
[Machine Learning 人工智能]
微调模型(Machine Learning 研习之十二)
现在正处于百模乱战的时期,对于模型微调,想必您是有所了解了,毕竟国外的大语言模型一开源,国内便纷纷基于该模型进行微调,从而开始宣称领先于某某、超越了谁。可到头来,却让人发现他们套壳了国外大语言模型对外开放的API。 好了,我们不说国内各种大模型宣称超过了谁,毕竟,嘴巴长在别人脸上,我们管不了,也管不着,吹牛终将是会露馅的! 当我们需要对开源大模型进行微调时,看看有几种方法可以做到这一点的! 网格搜索 手动调整超参数,直到找到超参数值的完美组合。 这将是一项非常乏味的工作,而且您可能没有时间去探索多种组合。 相反,您可以使用 Scikit-Learn 的 GridSearchCV 类来搜索您。 您需要做的就是告诉它您希望它试验哪些超参数以及要尝试哪些值,它将使用交叉验证来评估超参数值的所有可能组合。 例如,以下代码搜索 RandomForestRegressor 的最佳超参数值组合: from sklearn.model_selection import GridSearchCV full_pipeline = Pipeline([ ("preprocessing", preprocessing), ("random_forest", RandomForestRegressor(random_state=42)), ]) param_grid = [{'preprocessing__geo__n_clusters': [5, 8, 10], 'random_forest__max_features': [4, 6, 8]}, {'preprocessing__geo__n_clusters': [10, 15], 'random_forest__max_features': [6, 8, 10]}, ] grid_search = GridSearchCV(full_pipeline, param_grid, cv=3, scoring='neg_root_mean_squared_error') grid_search.fit(housing, housing_labels) 请注意,您可以引用管道中任何估计器的任何超参数,即使该估计器嵌套在多个管道和列转换器的深处。 例如,当 Scikit-Learn 看到“preprocessing__geo__n_clusters”时,它会在双下划线处分割该字符串,然后在管道中查找名为“preprocessing”的估计器并找到预处理 ColumnTransformer。 接下来,它在此 ColumnTransformer 中查找名为“geo”的转换器,并找到我们在纬度和经度属性上使用的 ClusterSimilarity 转换器。 然后它找到该变压器的n_clusters超参数。 同样,random_forest__max_features指的是名为“random_forest”的估计器的max_features超参数,这当然是RandomForest模型。 这个param_grid中有两个字典,因此GridSearchCV将首先评估第一个字典中指定的n_clusters和max_features超参数值的所有3×3=9个组合,然后它将尝试第一个字典中指定的所有2×3=6个超参数值组合 第二个字典。 因此,网格搜索总共将探索 9 + 6 = 15 种超参数值组合,并且每个组合都会对管道进行 3 次训练,因为我们使用的是 3 折交叉验证。 这意味着总共将有 15 × 3 = 45 轮训练! 这可能需要一段时间,但是完成后您可以获得如下参数的最佳组合:
2024-03-09
[Machine Learning 人工智能]
解决 github.com port 443: Timed out 的问题
国内访问github.com总是那么不竟如人意,时而无法加载网页,时而等我们抽完了一根烟后,它还处于转圈的状态。 虽然国内有gitee.com等诸多的代码托管平台,但却鲜有国人愿意去呢?其中的缘由,想必也不用我多说,大伙也都心知肚明了吧! 即便github.com在国内访问慢,或是加载不出来,我们也宁愿等它慢慢地加载出来,却不愿将代码托管于境内的平台。 github.com 托管了 qiucode.cn 站点 由于将 秋码记录 托管于 github.com上后,写些文章就得push上去,然而当我push上去时,却十有八九都会出现 github.com port 443: Timed out的错误,代码显然是无法push上去的了! 难道在国内,现在push或是pull github.com,都是要靠运气吗?偶尔可以,大多数都是报错。 可是,“运气”总不能实时来关顾我们,要是那样的话,我早去买彩票了,虽然有运气,买了彩票,它也不一定中奖,毕竟古话早就有言:朝里有人好当官。 然而,有没有一劳永逸的解决之道呢?答案那是肯定有的,要不然,也就不会有这么一篇文章了,您也就不会花费您宝贵的时间来浏览本文,寻求与我遇到同样问题的解决方案了。 当我们想要clone github.com上的一个项目时,出现以下错误,那都是家常便饭了。 从报错信息来看,很显然这是https请求超时,这是毋庸置疑的,毕竟我们访问github.com都是是好是坏的!您在terminal端不还是一样的请求超时嘛! 解决国内 push/pull github.com 项目出现 Timed out 的问题 毕竟,秋码记录 是托管于 github.com上,总不可能写了一篇文章,想要push到 github.com,这次出现Timed out的错误,就不push,而是等到下次再写文章时,再push,这显然不是我要的,毕竟,技术文章(在这里,我也就王婆卖瓜,自卖自夸咯)是有时效性的!说是这么说,但并不妨碍的。 能出现Timed out的问题,我们第一想到便是网络问题(有些事我们自己心里清楚就好了),其次才是本地git配置问题。 那么,我们暂且略过网络问题这一客观事实不谈,来说说本地git的配置是哪里出现问题,而导致了出现Timed out的问题呢? 我们还是回到 terminal,输入以下命令测试ssh是否成功? ssh -T git@github.com 如果,您也出现了上图的结果,那显然是配置的问题了。 我们再次测试下port 443是否也出现超时的问题? ssh -T -p 443 git@ssh.github.com 可以看出,端口 443 请求是没问题,那么,为什么clone项目时,却报出了port 443请求超时的错误呢? 我们大致从上面的ssh测试报错便可以得出结论了,那便是ssh连接超时了。 而要想解决ssh请求超时的问题,那就要从配置着手了,还是一样的在terminal输入以下命令。 vim ~/.ssh/config 而后在进入编辑状态,填写以下内容 # Add section below to it Host github.com Hostname ssh.
2024-01-27
[github]
选择和训练模型(Machine Learning 研习之十一)
当您看到本文标题时,不禁感叹,总算是到了训练模型这一节了。 是啊,在之前的文章中,我们对数据进行了探索,以及对一个训练集和一个测试集进行了采样,也编写了一个预处理管道来自动清理,准备您的数据用于机器学习算法,然而现在,我们可以选择并训练模型了。 训练集的训练与评估 我们从一个最基本的线性回归模型开始: from sklearn.linear_model import LinearRegression lin_reg = make_pipeline(preprocessing, LinearRegression()) lin_reg.fit(housing, housing_labels) 很好,至此,我们现在算是有了一个有效的线性回归模型,可以在训练集上试用它,查看前五个预测,并将它们与标签进行比较:: 第一个预测偏差很大(超过200,000美元!),而其他预测则更好,两个预测偏差约25%,还有两个预测 偏差不到10%。请记住,您选择使用RMSE作为性能测度,因此您希望使用Scikit-Learn的mean_squared_error()函数在整个训练集上测量该回归模型的RMSE,并将平方参数设置为False。 这总比没有好,但显然不是一个很好的分数,大多数地区的房屋价值中位数在120,000美元和26.5万美元之间,所以一个典型的68628美元的预测误差真的不是很令人满意。这是一个模型拟合训练数据不足的示例。当这种情况发生时,可能意味着这些特征没有提供足够的信息来做出好的预测,或者模型不够强大。 正如我们在上一章中看到的,修复欠拟合的主要方法是选择一个更强大的模型,为训练算法提供更好的特征,或者减少对模型的约束。这个模型没有正规化,这就排除了最后一个选项。您可以尝试添加更多功能,但首先您要尝试更复杂的模型,看看它是如何工作的。 您决定尝试DecisionTreeRegressor,因为这是一个相当强大的模型,能够在数据中找到复杂的非线性关系(后续篇章将更详细地介绍决策树): from sklearn.tree import DecisionTreeRegressor tree_reg = make_pipeline(preprocessing, DecisionTreeRegressor(random_state=42)) tree_reg.fit(housing, housing_labels) 现在模型已训练完毕,您可以在训练集中对其进行评估: 等等,难道这个模型真的很完美吗?当然咯,更有可能的是模型严重地过度拟合了数据。您怎么能确定正如你前面看到的,在您准备好启动一个您有信心的模型之前,您不想碰测试集,所以您需要使用一部分训练集进行训练,另一部分用于模型验证。 使用交叉验证进行更好的评估 评估决策树模型的一种方法是使用train_test_split()函数将训练集拆分为较小的训练集和验证集,然后针对较小的训练集训练您的模型,并针对验证集对其进行评估。这是一点努力,但没有太难,它会工作得相当不错。 一个很好的替代方法是使用Scikit-Learn的k_-fold交叉验证特性。下面的代码随机地将训练集分成10个不重叠的子集,称为fold,然后训练和评估决策树模型10次,每次选择不同的fold进行评估,并使用其他9个fold进行训练。结果是一个包含10个评价分数的数组: from sklearn.model_selection import cross_val_score tree_rmses = -cross_val_score(tree_reg, housing, housing_labels, scoring="neg_root_mean_squared_error", cv=10) ```Scikit-Learn```的交叉验证功能期望的是效用函数(越大越好)而不是成本函数(越低越好),所以评分函数实际上是RMSE的反面。它是一个负值,所以您需要切换输出的符号来获得RMSE分数。 让我们来看看结果吧: 现在决策树看起来不像以前那么好了。事实上,它的表现几乎和线性回归模型一样差!请注意,交叉验证不仅允许您获得模型性能的估计值,还允许您测量该估计值的精确度(即其标准差)。决策树的均方根误差约为66,868,标准差约为2,061。如果只使用一个验证集,则不会有此信息。但是交叉验证是以多次训练模型为代价的,所以它并不总是可行的。 如果您为线性回归模型计算相同的度量,您将发现平均RMSE为69,858,标准差为4,182。因此,决策树模型的性能似乎比线性模型稍微好一点,但由于严重的过拟合,差异很小。我们知道存在过拟合 问题,因为训练误差很低(实际上为零),而验证误差很高。 现在让我们尝试最后一个模型:随机森林调节器,随机森林的工作原理是在特征的随机子集上训练许多决策树,然后平均出它们的预测值。这样的模型组成的许多其他模型被称为合奏:他们能够提高性能基础模型(在本例中为决策树)。代码与前面的代码大同小异: from sklearn.ensemble import RandomForestRegressor forest_reg = make_pipeline(preprocessing, RandomForestRegressor(random_state=42)) forest_rmses = -cross_val_score(forest_reg, housing, housing_labels, scoring="neg_root_mean_squared_error", cv=10) 随机森林真的看起来非常有前途的任务!但是,如果您训练一个RandomForest并测量训练集上的RMSE,您将发现大约17,474:这要低得多,这意味着仍然存在大量的过度拟合。可能的解决方案是 简化模型,约束它(即,规则化它),或得到更多的训练数据。但是,在深入研究随机森林之前,您应该尝试来自各种类别机器学习算法的许多其他模型(例如,具有不同内核的多个支持向量机,可能还有一个神经网络),而无需花费太多时间调整超参数。目标是列出几个(两到五个)有前途的模型。
2024-01-14
[Machine Learning 人工智能]
回望这风雨飘摇的一年过后,我们终将要整束行囊继续前行
2023 这一年 时间倏忽而过,纵有再多的不甘,2023 这一年的日历终要翻过去了。这一年,或许还对很多事保持着一种执念,然而,随着 2023 年如东逝水一去不复返,也该放下那份执着,让我们挥手告别那处于风雨飘摇的 2023 年,毕竟,未来还很长,我们还得背上行囊踏上那远方的路,否则,赶不上停靠在路边的二路汽车了都! 2023 年年初为这一年预先设定的规划,实现了吗?然而,回答我们自己,是那无声的摇头。年初预定的规划,大抵也只有到了年末,我们对这一年复盘时,方觉得年初列出的计划清单,还是有那么多没有完成,更有甚者,清单上一项都没能实现,或许,此刻,我们会对自己发出一声苦笑,长吁责问自己,“一年的时间,竟然空不出一点时间来完成那年初既定的规划!” 无论是长吁短叹,还是责怪自己,我们总得为未来、新的一年起一份未来规划列表,顺带 2023 年还未完成的计划。 风雨过后,总能遇见太阳,只是自然界的现象,当然,也有例外,太阳有时让那厚实的云朵遮蔽了,日光便无法照耀大地,那阴郁之气却布满了上空,使这座城市处于压抑的一天,但我们相信,云朵总是会散开的,迟来的阳光,也会照射这片土地,用那光芒的温度去蒸发昨日的阴郁之气。 或许,用【风雨飘摇】这个成语来形容 2023 这一年,总觉得还不是那么恰当,因为 2023 这一年,并不像【风雨飘摇】这个词轻描淡写、一词带过,这四个字并不足以恰如其分地述说 2023 这一年。 这一年,承载着太多人的不甘;这一年,也让大部分撤离了那份职业;这一年,也让很大一部分人彻夜逃离了大城市,终将回到了可以安放灵魂的故乡。 然而,在 2023 这一年所积攒下来的诸多不甘、不忿、怨愤等阴郁之气,我们希望能借未来之光芒来吹散、蒸发那股消极、惨淡、压抑之气,在我们寄托于未来之光的时刻,我们也必须时刻充实自己,也只有这样,未来之光方能光顾到我们自己。 2023 年的既定计划 说来忏愧,2023 年年初既定要完成的计划,用这一年的时间,本是完成那份计划清单,绰绰有余,然而,一年到头了,回首这一年,却发觉,计划清单上竟然还有那么多未能实现的。或许,我们会长叹一声,“时间都去哪儿了?” 时间并没有去哪里游玩,而是一直傍我们左右,只是我们生活节奏快了,顺带也把时间扯上了。那一声,“时间都去哪儿了?”的感慨,是没来由的长吁短叹! 2023 年既定的计划: 编写一套具有 秋码记录 风格的 Wordpress主题 编写一套具有 秋码记录 风格的Typecho主题 更新基于Vue.js 2.X的开源 UI组件库 qiucode-ui 组件库 编写一套基于 React的开源UI组件库 让 秋码记录 全站使用自己开源的UI组件库 然而,到了 2023 年年末,回望计划清单时,发觉虽但没能全部完成,却在意料之外增添一项计划,实属难料的惊喜: 开源了一套由 Hugo驱动的 hugo-theme-kiwi主题 一套由 Hugo 驱动的博客主题 hugo-theme-kiwi 开源啦 实践多个Web3项目 研习人工智能领域 2023 年所欠下的计划,我们也只能将它们寄托于新的一年,希冀未来能够逐一地实现它们,以不负昨日之约。 我们将 2023 年所搁浅的计划,整理好,装进背囊,踏上远方之路,让未来之光吹散因在 2023 年所沾满了满身泄气、不甘、愤懑地压抑之气。 展望未来 昨日之事,已成定局,断然不可挽回,该是放下那份执念,去迎接明日的阳光。
2023-12-30
[生活情感]
1
2
3
4
...
11