duangsuse::Echo
716 subscribers
4.25K photos
127 videos
583 files
6.46K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
内存区域限制技能 get
https://ice1000.org/2018/04/27/CodeEditor/ #blog #fix

看完查找资料后,修复了我对一个单词的误解:

efficient 不是『足够』的意思,是『有效率』的意思
effective 是有效的意思
Trumeet/FlarumSDK 1+ 理解

快速阅览:

这是一个使用 Gson / OkHttp 的 Flarum JsonAPI 客户端程序

+ 它有一些客户端实例状态

Flarum API base URL

Task Executor, OkHttp Client, Gson 实例
身份验证 Token: interface TokenGetter { String getToken(); }


+ RequestBuilder 按照 base url, method, body, authentation, filters, page(*20 item/perpage) 和 json converter 生成 OkHttp 的 Request
+ internal.parser.jsonapi.Parser 将 Raw JSON Response 作为 JsonAPI 返回对象解析,返回 APIJSONObject 将被各种对象解析器 internal.parser.ObjectParser.JsonConverter<T> 读取到 Java 对象
+ Result<T> 给 T 结果附加了 OkHttp 的 raw response 和 raw api json object 以及 ID(目前为 0)
+ internal.parser.ObjectParser 定义了将 JSON 对象解析为 Java 对象的接口和辅助函数
+ internal.parser.converter. 定义了一些辅助这种转换器编写的基类
+ internal.parser.ContentParser 是空的 fallback JsonDeserializer<Content> (也是空的) 实现,如果不能作为 Api Json 解析,结果就是无意义的值
+ internal.parser.OkHttpUtils 是放错地方的 OkHttp Client API Call 请求封装,它支持同步使用 execute(request, apiManager, converters) 和异步使用 enqueue(request, apiManager, converters)

逻辑就是给原处理程序加上先判断
HTTP Status 成功、JSONAPIObject 解析成功且访问不包含错误、再转换为目标 Result<T> 的过程

+ internal.platform.Platform 是从 Square Inc 复制修改的逻辑,实际上就是弄一个 Executor... 本来目的是给 OkHttp 异步请求分配合适的执行者,可实际上它只能找到有 android.os.Build 的 Android 平台和创建利用 android.os.Looperandroid.os.Handler Executor 的(post 到 mainloop 去执行),否则默认就是新建 Thread 去执行,而且处理的地方也不在这里,在它的 Caller 那里...
这个类要是弄的好一点要使用 enum with constructor calls、java.util.Function、java.util.concurrent.Executors、java.util.concurrent.ForkJoinPool
This media is not supported in your browser
VIEW IN TELEGRAM
人生苦短,写点文字吧
duangsuse::Echo
https://github.com/duangsuse-valid-projects/Java-You-Dont-Know 过一周天这里甚至会重写我之前写的 Ruby 入门... 将会讲一些有趣的问题
没时间写内容了,看来得两个星期,解析组合子的事情也要推后了,好无聊啊,打字又变慢了
排版测试
#Cplusplus https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture

Lambda capture in C++11

#reveng https://github.com/freakishfox/xAnSo #recommended

即使作者的项目管理风格有点... 呃... 比较原始,而且作者貌似是自己能用了就跑路了,后来开了仨 issue 说是不能用或者建议作者给软件文档的也没有用的回复。

这个是看 @Trumeet 的 GitHub Star 的,不是我找的,我也不知道为啥 Yuuta 会看到这个

代码里有用 C++ 的匿名函数(比较类似 Java 的 Lambda expression,因为比起完整的『闭包』『高阶函数[1]』来说它更像一个语法糖)

如果有同学不懂的,可以去 wikipedia 看看,当然那个 [&] 是 capture all by value (copying) 的意思,不过我一般习惯指定好要捕捉哪些变量(习惯性,如果我写 C++ 的话。


[1]: 闭包(closures)可以实现高阶函数,高阶函数是可以接受函数和返回函数的函数(类似数学里的高阶函数)
在函数(functions)是 first-class 的时候可以实现,但把函数作为“值”[2]传递往往要考虑到一些东西,比如局部变量和 lambda calculus 的 lexical scoping 可能捕获到外部函数[4]的本地变量(UpValue),很多现代化的语言诸如 Lua, Ruby, Python 都支持闭包
闭包不应该和匿名函数混淆,即使在诸如 JavaScript(从第一个被 ECMA 标准化的版本开始的)一类的『函数式、脚本』语言里,他们是类似的,其类似主要是匿名函数是没有指定名字只能使用“引用”来调用的闭包

[2]: 值是 PLT(程序设计语言理论) 里的一个概念,可以类比“下面”实际目标机器『加减乘除』的参数(操作数,operands,指机器指令的操作数,比如 mov.i32/rr, add.i32)类型(机器数值),但在 PLT 里这个概念被泛化了,和 first-class[3] citizen 不应该混用,但是可以认为值是 first-class citizen
[3]: “第一类”对象:可以作为函数的参数和返回值、可以被“储存”(store)到诸如函数栈帧(frame)本地变量、全局变量的容器里,它也是 PLT 的概念
[4]: 也叫做“外部函数”(enclosing function);内部被嵌入的函数被称为“内部函数”(inner function),详情参见 wikipedia: Closure(Computer Science)
比如在 Lambda calculus (理论) 里,
true = λp. (λq. p)
false = λp. (λq. q)
这是 Church encoding 里 boolean (布耳值,详见布尔代数) 的表达方式
lambda 演算[5]是惰性求值(lazy evaluated)的,在 Haskell 里,类似的函数可以被用于替换 Haskell 内部的 if 语法
where 这里的 Haskell 是 Haskell 98 [语言标准] if 是 Haskell 内部钦定的语法,但利用 Haskell 的 Lambda abstraction if 也完全可以被替换掉,即使没啥用
在 Java 8 里,
import java.util.function.Function;

//... omitted for brevity
Function<
Function<Void, ? extends Object>,
Function<
Function<Void, ? extends Object>,
? extends Object>>
truef = p -> q -> p.apply(null);
//... omitted for brevity

(看 Java 的“FP”我都快晕了,跑,这里使用 wildcard 泛型是... 习惯,虽然这里泛型不协变(covariant)也没问题。
[5]: Lambda 演算:悠久历史(1930 年)的演算模型,其历史还可以追溯到 1920 年的组合子逻辑(Combinatory logic),和图灵机[6]鸡̶🐔你太̶美̶同一个历史时期,开始这个模型被创造来形式化描述数学(mathematics),lambda 演算是项 (term) 组成的形式化系统,其有三种项:
+ x: Variable
+ (λ x. M): (Lambda) abstraction
+ (M N): Application
基本的操作有两个,他们基于 绑定(命名): binding 和 替换: substraction 操作:
+ ((λx.M) E) _β= (M[x:=E]): β-reduction, 这是 binding 操作,替换后的 M 的上下文(context,Lambda calculus 一般名为 Γ, Gamma)里 x 变量就是 E 项了
+ (λx.M[x]) _α= (λy.M[y]): α-conversion, 这是 renaming 操作(也是一种性质),用于 abstraction variable 名字冲突时,它告诉我们 lambda 只是基于 term group 的 substract 抽象而已,和『参数』的名字无关
表示上,Lambda calculus 是左递归(Left recursive)的,这是说
λx. λy. x 表示 (λx. (λy. x))
Lambda calculus 已经被(隐式地)用于现在的绝大部分高级计算机语言,并且被诸多函数式编程语言(functional programming language)作为自己的理论基础使用,其理论已经比较丰厚繁杂,详情 wikipedia

[6]: 图灵机:阿兰·图灵大学时期于 1936 年提出的自动机计算模型,有一门叫 brainfuck 的编程语言图灵完全(图灵机兼容)可以作为图灵机的辅助理解范本;图灵机以打字机为原型,假设自己有一个无限长度的存储卡带和一个解释器,被编程的解释器读写卡带处理卡带上的数据。
和 Lambda calculus 不同,图灵机的数据[7]是线性(linear)的而不是树形的,1939 年 J. Barkley Rosser 证明了 λ 演算和通用图灵机是等价的
brainfuck 只有 8 条指令:+, -, <, >, ., ",", [, ]
brainfuck 之所以图灵等价是因为它也认为有一个无限大小的随机访问存储器,+- 用来操作当前存储单元指针下的数据、<> 用来移动数据指针、,. 用来做 I/O、[] 用于实现循环,当然也可以是不停机(non terminating) 的无限循环。
能够实现图灵机所有功能的自动机被称为是图灵等价,或者说,图灵完全(Turing complete)的
图灵机的性质比较适合进行文本处理,但实际上它只是概念上的计算模型而已
通用图灵机(universal Turing machine)启发了后面的冯·诺伊曼存储程序性计算架构(现在最通用的计算模型也是现在电子计算机技术的基础,哈佛架构优化的基础)的诞生,并且,Alan Turing 用它在 1936 年证明了停机问题(Halting problem)是不可解决的(当然他的导师 Church 同年也用 lambda calculus 证明了这个问题逻辑不可解,各自独立地)
[7]: Lambda calculus 里实际上只存在抽象而没有所谓的数据,这里是做了一个不恰当的比方
27.9k star,本身是模仿饿了么....
话说,刚才看到 bitcoin core 项目才 38k star... 看来中国的网络前端真的是不少啊
Vue 是什么.... 🙈 看来以后得学习一下了
咳咳.... 马上继续写书去算了( #Java 真的是时间永远不够用
看起来我打算加入的章节,这次恐怕都没有时间加入了呢。

这个星期主要是看了三本书,先说说基本感想。

《手把手教你学 FPGA 设计》:巨好评 👍👍
作者果不其然是真·高手啊!况且现在敢入、能入电子工业和无线电的人大概是少数吧,当初进入已经非常了不起了,现在又来教下一辈,还是以这么通透的理解层次!

而且他还在华为海思半导体公司加入了新一代无线通讯技术(貌似是 4G 或以上?) 跳频 OFDM 无线多地址通讯系统的研发,他技术行文的简洁性也透露着自己的实力、例子也举的非常合适,非常符合工程实践,有 SDRAM[1]、UART[2]、VGA[3]、LED[4] 显示温度计、边缘扫描图像处理硬件等,但是书居然只有两百多面,而且算法(Verilog 硬件描述语言)还写全了!这个 PLD 教学真可以说是中国第一简单实用快速!


[1]: SDRAM: 同步[6]动态随机访问存储器,Synchronized Dynamic Random Access Memory,它是一种易失性(volatile)存储器,和 SRAM (静态)的区别是因为内部晶体管电荷保存时间有限,必须按照固定频率刷新才能保证内部数据不会丢失,而 SRAM 就不需要;一般来说高质量的存储用途(比如缓存)会使用 SRAM,因为它不需要浪费时间去进行刷新操作
不都用 SRAM 的原因是它太贵了,DRAM 一个晶体管就可以实现的存储容量(比如 1* bit) SRAM 要六个 🤪 体积大,而且用户买不起。
[2]: UART: 通用异步收发传输器,Universal Asynchronous Receive Transmit
这娃是传输字符用的(类比 TTY),嵌入式开发里一般用它调试目标板子。[5]
[3]: VGA: 最开始由 IBM 设计的视频接口标准“视频图形阵列”,Video Graphics Array
[4]: 发光二极管,这里指 “8” LED 阵列式数值显示用的元件

[5]: 板子一般指单片机或者嵌入式片上系统;
最开始我把 UART 误解为“通用并行设备总线”了(伪造 USB,通用串行设备总线,误)
[6]: 同步是指和其他器件(一般是微处理器、微控制器)的时钟节拍信号同步对齐


《零起点 Python 机器学习快速入门》:中评 😐
作者是一个做中文字库的(字王工作室),自产有《中华大字库》、TopQuant 足彩分析等,也是一个其他信息行业奠基者的角色,(对我来说)是个先辈,但是他对程序设计的理解有点独特但不是很深刻,书上的图示、算法接口资料还比较齐全,
示例数据集主要讲的是 Iris 爱丽丝花卉子种属数据集,以及一个 CCPP 发电厂电力输出数据集。

全本书讲了 sklearn (scikit)、Pandas、Matplotlib 的使用,当然没有提到 Numpy、Numba、OpenCL、OpenMP、PyCUDA 等高性能计算库的使用(“黑箱”教学),但是提了名字

算法没有讲太多算法细节,只是给你几个封装函数做学习、测试数据切分 (ai_data_cut)、学习 (mx_*)、回归 (predict 方法)、测试 (ai_acc_xed) (用于判断数据预测的准确率,就是对 test 数据集,准备好预测到的结果,取实际 test 的结果,判断 (误差小于目标 k 的结果项目份数/总份数)

前面还教你如何进行『分类名称』“矢量”化(就不在这里喷这个名词使用的错误了[1],虽然可能不是他自己最开始用的)...
这里不吐槽任何槽点,但是本书的槽点还是很多的,看上 100 面大概能找到十七八个,不过不得不说对于机器学习入门来说这本书也不错(即使里面有些文字我打算专门吐槽一下...)。
再者,因为我这里绝对没有任何其他的机器学习书了...

《持续轻量级 JavaEE 开发》:好评 👍
作者们都是 RedHat JBoss 多项目的资深工程师、项目经理什么的,面向对象编程大师。


然后马上要放暑假了,真是 🎉
GeekApk 又有一次复活的机会了,正好我最近在看 JavaEE,刚对 EE 那些真的是有点复杂的依赖注入、Observer、Interceptor、单元测试、Service locator pattern、反射元编程和声明(annotations) 有点感觉了
打算弄点大新闻出来 🐸


[1]: 矢量化:这里是指,对于一个数据表(书上的是 Iris 种属分类)
如果要学习(数据分析)的一项是(可能不可导、不可进行传统统计概率数值运算的)聚合量(product type)比如一个 strcharhomogenous product type)那就先将其『标号化』、学习,再在回归的时候映射回来
矢量,在物理上是有方向的量[2],数学上(尤其线性代数)矢量化是指把矩阵转化为线性序列的形式,请问这里它的宾语(目标)是指『这个数据表 pandas.DataFrame』呢?还是 Python 的 built-in type str 呢?
不管怎么样,看起来都有点不太对吧?哈?算了....


vec(A) = {
a[1,1], ..., a[m,1],
a[1,2], ..., a[m,2],
a[1,n], ..., a[m,n] }(^T
)

简而言之就是把 2x2 矩阵 { a b;; c d } 变成元组 [ a c b d ], 看上面的递推式子也知道了

缺点当然是很明显的,比如 Iris 分类器的例子,作者就这么对三种种属『“矢量化”』了一波(取的『编号』,虽然那实际上是逼近的参数之一.... 都是 1,2,3 这种),Linear regression 的结果很差很辣鸡,只比随机三选一好一点。
然而实际上可以多准确呢?同数据集 KNN 分类器(K-最近邻分类法,最简单的机器学习算法之一,特征聚合映射到 N 维空间判距离上 k 最近邻中数目最多的分类,用作者的话,当然我觉得还行的就是『物以类聚』)学习后给出的判断准确率是 100%!

何况,作者『映射』分类预测结果回来(实际上没有映射回 str,但这里和我说的实际上是一个情况)的时候使用的(浮点)算法是直接 truncate 掉小数部分然后 if else if.... (不如 switch ....),还不如四舍五入好呢(不要忘记了这个『矢量』实际上代表的是一个分类!)

作者自己的确是做数据分析的,可是他对编程的理解.... 我觉得真的不是特别值得学习

我可没有随便对自己完全不理解的东西乱说话,至少我能找到一篇文章给我背书:
Conmajia::CodeProject::前馈全连接神经网络和函数逼近、时间序列预测、手写数字识别
这里面没有 Python 书里作者所谓的『矢量化』, 但只是学习模型的不同而已(线性回归 vs. 人工神经网络),不过 Sklearn 有 one-hot encoding 的实现,作者还是要用『矢量化』定 1,2,3,明明说都到『CPU 加法器』的级别了,却连二进制都没注意到,也真是服气了....

>>> from sklearn import preprocessing
>>> le = preprocessing.LabelEncoder()
>>> le.fit([1, 2, 2, 6])
LabelEncoder()
>>> le.classes_
array([1, 2, 6])

[2]:第一次的时候搞错了... 物理上那个是向量,基本无关的东西
duangsuse::Echo
咳咳.... 马上继续写书去算了( #Java 真的是时间永远不够用 看起来我打算加入的章节,这次恐怕都没有时间加入了呢。 这个星期主要是看了三本书,先说说基本感想。 《手把手教你学 FPGA 设计》:巨好评 👍👍 作者果不其然是真·高手啊!况且现在敢入、能入电子工业和无线电的人大概是少数吧,当初进入已经非常了不起了,现在又来教下一辈,还是以这么通透的理解层次! 而且他还在华为海思半导体公司加入了新一代无线通讯技术(貌似是 4G 或以上?) 跳频 OFDM 无线多地址通讯系统的研发,他技术行文的简洁…
#Python 四舍五入能『优化“矢量化”后的预测结果准确率』一看可能不是正确答案,但是我会用实践测试一下它是不是正确的

首先看看这个 wiki 页面,我们提取 HTML 表格数据(下面的编程风格不值得学习,复用性也很差,是我自己瞎堆的,因为我不熟悉 JQuery,,,)

let table = $('table.wikitable.sortable')
.filter((_, e) => e.firstElementChild.innerText === "费雪鸢尾花卉数据集").get(0);

let data_body = $(table).find('tbody').get(0);

//

{ let result = [];
for (let t of data_body.children) {
let [x, y, z, w, o] = t.children;
result.push(...[x,y,z,w,o]);
}}

🙈 不好意思,这个是矢量化(删除线)

let result = $(data_body.children).map((_, t) => [($(t.children).slice(0,2+1).map((_, c) => Number.parseFloat(c.innerText))).get().concat(t.children[4].innerText)])
;

刚才本来用的是 array expansion(其实有点 deficient)[...xs, a] 的,后来发现 JQuery 的 map 好像会自动 flatten... 就换成这样了
slice2+1 是因为 JQuery 的 slice 切片是右闭(exclusive)区间,2 是输出的最后一个 index

然后我们输出 CSV,上 Python Pandas + Sklearn 分析吧,首先我们已经确认,数据里没有特殊字符(和 CSV 语义冲突的)需要处理

result.map((_, t) => t.join(',')).get().join("\n")

好的程序应该反映出其所处理的数据的结构,这里 map 里的闭包输出每个 row 的 toCsvString 操作结果(join each column);最后每行再合并(join)就生成了 CSV 结构

复制下对象、注意去掉两边的 "" dquote,然后保存到本地
Iris.csv
3 KB
#ML #Python Iris 数据集
duangsuse::Echo
#Python 四舍五入能『优化“矢量化”后的预测结果准确率』一看可能不是正确答案,但是我会用实践测试一下它是不是正确的 首先看看这个 wiki 页面,我们提取 HTML 表格数据(下面的编程风格不值得学习,复用性也很差,是我自己瞎堆的,因为我不熟悉 JQuery,,,) let table = $('table.wikitable.sortable') .filter((_, e) => e.firstElementChild.innerText === "费雪鸢尾花卉数据集").get(0);…
#ML #Python 接下来安装一点用于数据分析的东西

pip3 install --user --compile -U pandas matplotlib sklearn

如果有权限你也可以去掉 --user flag,-U 的意思是如果有的话安装更新
我们使用 Python 3,当然,要是有 IPython 和 Spyder 这种为数据分析 REPL 优化的东西就更好了,不过下面直接用 IPython3

现代机器学习算法主要包含概念学习、规则学习、基于解释学习、基于实例学习、遗传学习、强化学习、贝叶丝学习、神经网络、决策树等分类,当然我也不是很清楚都有啥大区别,反正就是数据分析就对了。

然后函数式编程一般有以下特征 #FP
+ 闭包、高阶函数、函数作为值
+ 基于 Lambda calculus、柯里化(currying)
+ 纯函数无副作用、引用透明、惰性求值
+ 模式匹配,递归作为程序控制基本方式
.... 跑题了,打住。

机器学习某度词条里说是”机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。“

其实你记住,无非就是数学的统计、概率、函数、微积分,然后加上计算机科学的算法、软件工程什么的最多了,其他的我们这些渣渣也用不到。

然后我现在”尤其“喜欢神经网络,不过很可惜还没有入门😑 不是因为神经网络复杂(一般我们手动会讨论的基本都是些小网络和网络结构什么的,然后还会讨论学习算法,神经元基本模型本身并不复杂)

在等待下载的时候可以先定义几个函数,首先我们要用 sklearn 里实现的 linear regression 学习实现
我可不擅长黑箱教学是̶因̶为̶话̶太̶多̶的̶缘̶故̶么̶

说起来这个教程居然还提到了 Python 有 Complex numbers(数学上的复数,包含实数和虚数单位)算是『惊喜』吗?

然后我们有了算法输入了(按照某学姐的说法,神经网络就是一个带有未知参数的程序,那机器学习的很多算法也差不多,这里是有仨输入仨未知系数一输出的数学函数,我们的学习算法会”猜“一个最优化的系数组)
那先按某个比率 k 切分学习数据和测试数据来的,定义函数 splitTrainingTestData

from pandas import DataFrame
def splitTrainingTestData(ts: DataFrame, kratio: int = 60) -> (DataFrame, DataFrame):
  assert kraito <= 100, "kratio must be valid integral percentage"  
(txs, drs) = ts.values.tolist(), round(100 / kratio)
training = txs[::drs]; testset = [x for x in txs if x not in training]
return training, testset

... 刚才把 kraito 放到 ts 前面去了,Haskell 写多了的结果... (柯里化)
有点秀而且华而不实甚至有问题(跑)其实实践中不应该这么做,但是这里不是实践,所以推荐大家打开思路去实现算法
然后考虑一下最后的验证,测试预测准确率的函数 verifyRegressionAccuracy
当然,为了优雅性这时候可以给表格加上头(header)了,就是在它的第一行写上 x,y,z,w... 就是给数据列命名

def verifyRegressionAccuracy(ts: DataFrame, emax: float = 0.1, npredict = 'predict', ntruth = 'real') -> float:
predicteds, truths = ts[npredict], ts[ntruth]
acceptables = [t for (i, t) in enumerate(predicteds) if abs(t - truths[i]) <emax]
return len(acceptables) / len(predicteds)

总之就是先弄出 acceptable result 然后 len 取分数啦
然后简单 play 一下,Python 表达起来也很方便

+ (书上的例子)Pip 已安装软件包

from pandas import DataFrame
from pkg_resources import working_set
import re

dists = [(d.project_name, d.version) for d in working_set]
pkgs = DataFrame()
pkgs['name'] = [n for (n, _) in dists]
pkgs['version'] = [v for (_, v) in dists]

pkgs.tail(5)
pkgs.sort_values('version').head(10)
pkgs.describe()

pkgs['version'].describe()
pkgs['version'].map(lambda v: int(re.sub('rc|dev|\.','', v))).astype(int)

隐隐约约会感受到 Python 的确是数据处理很方便,有不少遍历语法(slice 和复制的 [:] 下标、list comprehension [... for ... in ... if ...]
但是!在其他新兴的编程语言(比如 Kotlin)里!这些功能基本都是可以直接用面向对象多态重载、运算符重载、高阶函数定义出来的! 🤔

+ 简单的数据折线图(plot)

from matplotlib import pyplot as plot
from pandas import Series
from math import sin

然后一个简单的 sin series, 很经典吧?

xs = range(0,200, 3)
很可惜没有使用 float 的 range... 也罢

ys = [sin(x) for x in xs]

但是数据不容易看见,谁对着那堆数字有感觉啊!
数据可视化!

plot.style.available ... 看看可以有啥绘图风格

plot.style.use('Solarize_Light2')

然后

Series(ys).plot()
或者
plot.plot(ys)

均可,之后可以选择 plot.show() (貌似没有用)
plot.savefig('path.png')


duangsuse::Echo
#ML #Python 接下来安装一点用于数据分析的东西 pip3 install --user --compile -U pandas matplotlib sklearn 如果有权限你也可以去掉 --user flag,-U 的意思是如果有的话安装更新 我们使用 Python 3,当然,要是有 IPython 和 Spyder 这种为数据分析 REPL 优化的东西就更好了,不过下面直接用 IPython3 现代机器学习算法主要包含概念学习、规则学习、基于解释学习、基于实例学习、遗传学习、强化学习…
然后可以开始了

from pandas import Series, read_csv

iris = read_csv('Iris.csv', encoding='utf-8', parse_dates=[], index_col=False)

然后我们就有了 Iris 数据集的工作实例(working set)(跑

先看看
In [39]: iris.describe()
Out[39]:
                x           y           z
count 150.000000 150.000000 150.000000
mean 5.843333 3.057333 3.758000
std 0.828066 0.435866 1.765298
min 4.300000 2.000000 1.000000
25% 5.100000 2.800000 1.600000
50% 5.800000 3.000000 4.350000
75% 6.400000 3.300000 5.100000
max 7.900000 4.400000 6.900000

count 是整个列表的求和
mean 是平均值、std 是方差
min, max 肯定都知道
50% 是中位数,其他 ?% 依此类推
In [40]:
iris['w'].value_counts()
Out[40]:
versicolor    50
virginica 50
setosa 50
Name: w, dtype: int64

In [43]:
iris.tail(5)
Out[43]:
       x    y    z          w
145 6.7 3.0 5.2 virginica
146 6.3 2.5 5.0 virginica
147 6.5 3.0 5.2 virginica
148 6.2 3.4 5.4 virginica
149 5.9 3.0 5.1 virginica

好了,已经说明问题了,现在我们要根据 f(x,y,z) 和它的结果 w 学习 f 这个曲线

不过有一个问题,就是 w 不是数值怎么量化,那我们就先看看按 0, 1, 2, ... 『文本量化』分会有怎么样的结果(怎么感觉和以前我把 Unification 当成泛化(Generalization) 的时候一样)

iris['id'] = Series().astype(int)

def vectorize(w,i, cname='w', cid='id', iris=iris): iris.loc[iris[cname]== w, cid] = i

In [3]: vectorize('setosa', 0)

In [4]: iris.head(5)
Out[4]:
     x    y    z       w   id
0 5.1 3.5 1.4 setosa 0.0
1 4.9 3.0 1.4 setosa 0.0
2 4.7 3.2 1.3 setosa 0.0
3 4.6 3.1 1.5 setosa 0.0
4 5.0 3.6 1.4 setosa 0.0

vectorize('versicolor', 1)
vectorize('virginica', 2)

OK, 这就是”矢“量化
iris.to_csv('Iris_vectorized.csv', index=False)

print (open('Iris_vectorized.csv').read())

In [17]: iris['id'].value_counts()
Out[17]:
2.0    50
1.0 50
0.0 50
Name: id, dtype: int64


然后进行数据预处理切分,之前的算法因为还有点偏差所以就不用了

from sklearn.model_selection import train_test_split

切分数据

iris_ds = iris.copy()

trainset, testset, trainsetid, testsetid = train_test_split(iris_ds, iris_ds['id'], train_size = 0.6)

del trainset['w']

trainset.describe()
trainsetid.describe()

就不填 random_state
然后直接用 sklearn 的算法学习

from sklearn.linear_model import LinearRegression
from math import floor

lreg = LinearRegression()
lreg.fit(trainset, trainsetid)

我们刚才”学习“了这些数据,看看我们能得到什么:

In [50]: testset.head(3)
Out[50]:
      x    y    z           w   id
91 6.1 3.0 4.6 versicolor 1.0
73 6.1 2.8 4.7 versicolor 1.0
79 5.7 2.6 3.5 versicolor 1.0

预测一下(”下面“都是 numpy 高性能计算的,这还有一层封装... 不过 pandas 也够了)

testset_truth = testset['w']
del testset['w']

testset['predict'] = lreg.predict(testset)

然后手工看看结果

value_map = {-1: 'setosa', 0: 'setosa', 1: 'versicolor', 2: 'virginica'}

testset['guess'] = testset['predict'].map(lambda x: value_map[floor(x)])
testset['w'] = testset_truth

🤔
duangsuse::Echo
然后可以开始了 from pandas import Series, read_csv iris = read_csv('Iris.csv', encoding='utf-8', parse_dates=[], index_col=False) 然后我们就有了 Iris 数据集的工作实例(working set)(跑 先看看 In [39]: iris.describe() Out[39]: x y z count 150.000000…
分类的准确性有点可怕...:

看来线性回归也... 😟 不过很可惜,verifyRegressionAccuracy 只支持数值表项,看来只能另外写准确率判断了:

errors = testset[testset['w'] != testset['guess']]

In [32]: len(errors) / len(testset) * 100
Out[32]: 8.333333333333332

8.3%
的错误率!

— Question: 同一个 linearreg,那原作者分类的准确率为啥那么低

因为我的『向量化』是 one-hot encoding (独热码编码)的啊!

如果我写完全等价的实践(1,2,3 + round),你猜准确率又是怎么样的?

首先我们的回归结果是转换为文字形式的,试试数值形式:

from pandas import Series, read_csv
iris = read_csv('Iris.csv', encoding='utf-8', parse_dates=[], index_col=False)
iris['id'] = Series().astype(int)


def vectorize(w,i, cname='w', cid='id', iris=iris): iris.loc[iris[cname]== w, cid] = i
vectorize('setosa', 0); vectorize('versicolor', 1); vectorize('virginica', 2)

from sklearn.model_selection import train_test_split
iris_ds = iris.copy()

trainset, testset, trainsetid, testsetid = train_test_split(iris_ds, iris_ds['id'], train_size = 0.6)
del trainset['w'], trainset['id']


from sklearn.linear_model import LinearRegression
from math import floor

lreg = LinearRegression()
lreg.fit(trainset, trainsetid)

testset_truthw, testset_truthid = testset['w'], testset['id']
del testset['w'], testset['id']
testset['predict'] = lreg.predict(testset)
testset['id'] = testset_truthid

from pandas import DataFrame
def verifyRegressionAccuracy(ts: DataFrame, emax: float = 0.1, npredict = 'predict', ntruth = 'real') -> float:
predicteds, truths = ts[npredict], ts[ntruth]
acceptables = [t for (r, t) in zip(truths, predicteds) if abs(t - r) <emax]
return (len(acceptables) / len(predicteds)) *100

verifyRegressionAccuracy(testset, 1.0, 'predict', 'id')

结果是误差 100% 在 1.0 以内。[1]

== 然后再试一次:

vectorize('setosa', 1); vectorize('versicolor', 2); vectorize('virginica', 3)
iris_ds = iris.copy()

trainset, testset, trainsetid, testsetid = train_test_split(iris_ds, iris_ds['id'], train_size = 0.6)

del trainset['w'], trainset['id']

lreg = LinearRegression()
lreg.fit(trainset, trainsetid)

testset_truthw, testset_truthid = testset['w'], testset['id']
del testset['w'], testset['id']

testset['predict'] = lreg.predict(testset)
testset['id'] = testset_truthid

— 修改后的逻辑
In [14]: verifyRegressionAccuracy(testset, 1.0, 'predict', 'id')
Out[14]: 100.0
我们的依然是 100%,然后 0.1 的误差是 48%

然后使用独到的 1,2,3,... 序列:
In [23]: verifyRegressionAccuracy(testset, 1.0, 'predict', 'id')
Out[23]: 100.0 然后 0.1 的误差是 45%

🥺 打脸了。好像完全可以算在误差内嘛...

— 实际情况

所谓打脸是因为我不知道作者要『量回归』还 map 了一次 round
至于 round 之后的误差(即使 round 的结果和之前绝对值线性距离计算的也有很大关系...)... 嘻嘻 🌝

testset['predict'] = testset['predict'].map(round)
verifyRegressionAccuracy(testset, 1, 'predict', 'id')

结果是 96%... 好像又是差不多,欸奇怪了 🤔 真实无解

[1]: 后来发现,我在训练的时候忘记删掉了 id 参数... 它好像找到了一个作弊的方式 🤪
虽然比较辣鸡的算法显然也不能把 id 的系数提高到多少... 但是线性回归或许可以猜出来?