About Device
Version
点击进入, 不是 Android Version
哦!Build Number
输入手机密码激活 Developer ModeAdditional settings
Developer options
, 点击进入OEM unlocking
USB debugging
安装方法1: 上面链接可以独立下载 Platform Tools 并且 手动安装 USB Driver.
安装 Platform Tools:
List of devices attached
下方显示手机列表即为成功.安装 USB Driver:
usb_driver
文件夹devmgmt.msc
打开 Device ManagerUpdate Driver
弹出更新驱动界面Browse My compute for drivers
Let me pick from a list of available drivers on my computer
Show All Devices
上点击 Next 下一步Have Disk...
usb_driver
文件夹中的 android_winusb.inf
文件Android Bootloader Interface
后点击 Nextfastboot devices
展示一个列表, 表示安装成功安装方法2: 下载 Android Studio 安装, 在 SDK Manager
中安装
Android API 34
下面的 Android SDK Platform 34
Show Package Details
Android SDK Build Tools 34
, Android SDK Platform Tools
, Google USB Driver
注意: 此步骤操作会格式化手机, 提前备份好数据
CMD 运行命令
1 | # 查看设备状态 |
再次进入 Developer Mode
Additional settings
Developer options
, 点击进入OEM unlocking
已经处于开启状态, 并且不可以手动关闭, 表示激活成功.参考: https://www.youtube.com/watch?v=nQatU6AilHY&t=5s&ab_channel=SUPERSUPATCHER
在官方 twrp 页面下载的软件版本只支持 Android 11 版本, 需要在 https://xdaforums.com/t/twrp-3-7-0-13-instantnoodle-twrp-for-oneplus-8-8pro-official-beta-3.4341707/ 下载支持 Android 12 的 ext4
或 Android 13 的 erofs
版本 img.
1 | adb devices |
在 GitHub https://github.com/topjohnwu/Magisk/releases 下载 Magisk 最新版本, 将 Magisk-v26.x.apk
复制处一份到 Magisk-v26.x.zip
原教程在此处将其复制到 U盘中, 并且在 twrp 中对手机进行了格式化操作, 重启 Reboot 选择 Recovery 重新进入 twrp, 我这里并没有进行.
直接将 zip 复制到手机硬盘 Download 文件夹下. 在 twrp 系统中选择 Install, 点击 Select Storage 选择刚刚的 zip 文件, 滑动安装 Magisk 到 recovery_a 系统中.
回到首页, 点击 Reboot - System 回到手机系统.
这时已经有 Magisk 京剧脸图标表示安装成功, 如果没有在手机内存找到 Msgisk-v26.x.apk 重新安装, 就会出现该图标.
首次进入 Magisk 后, 提示 Requires Additional Setup
选择 OK (如果重启, 重启后再进入 Magisk 后, 提示 Requires Additional Setup
) 选择 Direct Install(Recommend)
完成后点击 Reboot 重启.
至此, 已经完成了 Magisk 安装, 获取到 ROOT 权限.
参考: https://www.youtube.com/watch?v=3ZD3tb6FQvY&t=270s&ab_channel=SUPERSUPATCHER
到 https://www.kali.org/get-kali/#kali-mobile 下载 OnePlus 版本的 image 到手机 Download 文件夹.
在 Magisk 的 Modules
中, 点击 Install from storage
, 选择 nethunter-xx-xx-xx-kalifs-full.zip
确认安装即可.
安装后出现 NetHunter, NetHunter-Terminal 等软件, 开启需要授权 ROOT 权限才可以正常运行.
其他默认未安装的软件, 在 Store 中 有下载, 之后需要 ROOT 权限在 Magisk 的 SuperUser
进行管理.
如果手机链接电脑之后, 只显示充电, 没有弹窗提示 Use USB for
的列表, 那么有可能是因为数据线本身只支持充电, 不支持数据传输, 这一点很多网上的解决方案并没有提及.
弹窗选项一般为
这里选择 File Transfer
之后即可.
参考: https://www.shujuwa.net/android/cannot-detect-device
adb server version (22635) doesn't match this client (41)
因为我电脑本身有 Android Studio 和 独立下载的 Google Platform Tools, 并且对后者升级过后, 运行两者的 adb 时都报这个错.
开始看其他文章说因为有两个 adb 环境, 版本不同引发的冲突, 于是升级了 Android Studio 里面的 adb 环境版本, 但是运行二者仍然均无效. 也尝试了删除 C:\Users\xxx\.android
文件夹, 无效. 后来干脆删除独立版本的 adb 工具, 只保留 Android Studio 在 C:\Users\xxx\AppData\Local\Android\Sdk\platform-tools
内置的版本, 尝试仍然无效.
这时想到是否因为系统内存或某个地方仍然残留了老版本的 adb 信息, 于是重启, 再次运行 adb devices
启动 adb server 成功, 展示 devices 列表成功.
参考: https://www.cnblogs.com/yhjoker/p/9028900.html
安装 NetHunter 后, 正常有4个软件图标, 有时 Terminal 安装失败只有3个图标, 这时需要进入 NetHunter Store (三个其中的一个) 进行手动安装 Terminal. 如果最新版本安装一直失败, 可以选择安装之前的 2020 年版本, 秒成功.
]]>这时可以在前期无脑的定义日志清理策略:
查看当前被 Docker 占用的磁盘空间大小
list-docker-logs.sh
1 |
|
chmod +x list-docker-logs.sh
无脑清理所有由 Docker 产生的日志
clear-docker-logs.sh
1 |
|
chmod +x clear-docker-logs.sh
使用定时任务自动清除
使用 crontab -e
命令添加定时任务
首先在底部添加一行 0 5 * * * /path/to/clear-docker-logs.sh
.ssh/ssh-key-xx/
的内容各自有如下结构:1 | .ssh/ |
其中 .ssh 文件夹内由 ssh-keygen -t RSA -C email
生成, .gitconfig
是配置文件, .gitignore_global
是全局 ignore 配置文件, .stCommitMsg
是 commit 信息模板.
.gitconfig 文件模板:
1 | [user] |
.gitignore_global 文件模板:
1 | *~ |
使用 ssh 自带的 config 功能
配置 ~/.ssh/config
文件
1 | Host zs |
上面配置的意思为, 使用 zs
账号时将 github.com
替换成 zs
别名, 例如 git clone git@zs:username/project.git
, 这时 git@zs
将对 张三账号有权限. git@ls
将对李四账号有权限.
在首次设置过远程地址 git remote add origin git@zs:...
或克隆远程地址 git clone git@zs:...
之后, 再使用就正常进行操作即可.
方法 1: 参考 Windows.
方法 2: 安装 docker, 在 ~/.zshrc
中定义函数, 用于调用 docker 的 git 镜像, 实现多账号功能
1 | function gitzs () { |
使用 gitzs
命令 替代 git
即 gitzs clone git@github.com:username/project.git
将对张三账号有权限. 同样, 使用 gitls
命令替代 git
将对李四账号有权限
之后都使用 gitzs
和 gitls
替代 git
命令, 实现对张三李四账号的控制.
在Github 下载源代码编译, 或者直接下载 Release 中预编译的最新版本, 之后得到一个 tdl
或 tdl.exe
文件
登录, 这里的 NAMESPACE 是自定义的一个值, 以便后门使用
1 | .\tdl.exe login -n NAMESPACE -d "C:\bin\Telegram\tdata" --debug --proxy socks5://127.0.0.1:7890 --reconnect-timeout 30s |
PS: 注意, 之后的命令其他教程没有添加 `-n` 或 `--proxy`, 精测试每条命令都必须携带这两个参数, 登录时的各种参数并没有自动继承到后续的命令行中
查看群组ID, 会有 ID-Type-VisibleName-Username-Topics
的一个列表
1 | .\tdl.exe -n NAMESPACE --proxy socks5://127.0.0.1:1080 chat ls |
导出群组图片/视频列表, 会有一个 tdl-export.json
文件
1 | .\tdl.exe -n NAMESPACE --proxy socks5://127.0.0.1:1080 chat export -c 1589558175 |
批量下载
1 | .\tdl.exe -n NAMESPACE --proxy socks5://127.0.0.1:1080 dl -f ./tdl-export.json |
单个下载: 最后的 url 在消息中右键获取
1 | .\tdl.exe -n NAMESPACE --proxy socks5://127.0.0.1:1080 dl -u https://t.me/.../.. |
参见 人工智能学习 1 - 基础工具安装 or 参见官方文档 Installing Jupyter
使用 jypyter notebook
命令启动程序, 该程序会启动一个网页. 参见 Running the Notebook
新建 Python3 (ipykernel)
保存 .ipynb
文件到指定位置
输入框
加上 输入框下面的 输出区域
ctrl+enter
运行代码alt+enter
创建新单元b
below 创建新单元a
ahead 创建新单元dd
删除单元func?
展示方法参数返回值func??
展示方法源代码shift+tab
提示函数参数!cmd
创建一个子 shell 运行命令, 运行结束后子 shell 退出.%cmd
ipython 魔法命令, 在当前 shell 中执行 cmd 命令, 其作用在后续保留上下文继续有效.回归 regression
分类 classification
全连接网络 fully connected network FC
卷积神经网络 convolutional neural network CNN
样本 sample
模型 model
输入 inputs
输出 outputs
特征 feature
特征图 feature map
隐藏层 hidden layer
参数 parameter: 通过学习可以优化
超参数 hyperparameter: 根据经验设置, 一般不在学习过程中优化
权重 weight W
偏置 bias b
迭代次数 epoch
批量大小 batch size bs
学习率 learning rate lr
迭代次数 step
卷积核 kernel
通道 channels
过滤器 filter: filter是卷积核的向量, 与输出同维度
填白 padding p
步长 stride s
池化 pooling
激活函数 activation function
损失函数 loss function L(y',y)
代价函数 cost function J(W,b)
: 平均损失
优化 optimize
优化器 optimizer
线性 linear
非线性 non-linear
梯度 gradient
梯度下降 gradient decent
导数 derivative
偏导数 partial derivative
选择 系统
, 安装方法
, 语言: Python
, 计算平台
之后就出现对应的安装命令了.
1 | import torch |
数据初始化
1 | # 使用其他数据类型创建 |
数据类型转换
1 | # tensor 类型数据转换 |
tensor 数据属性
1 | ts.shape 或 ts.size() # tensor 形状 |
1 | # tensor 形状转换 |
将数据存储到 cuda 进行运算
1 | print(f"tensor store device {tensor.device}") |
1 | # 以 _ 结尾的函数 表示 inplace |
向量乘法:
矩阵乘法:
参考: https://www.jianshu.com/p/9165e3264ced
1 | x = torch.tensor(1.) |
requires_grad=True
将会追踪该 tensor 的所有操作.backward()
自动计算所有 grad 梯度.grad
属性上人, 动物, 计算机 看到的是一样的世界么?
人: 光 - 视觉系统 - 总结概念
计算机: 图片像素矩阵 - 模型 - 模型结果
图片: 灰度图(单通道), 彩色图(三通道 RGB)
二维数据展开, 构建全连接网络, 通过 softmax 计算得出多分类问题概率
缺陷:
m 目标图像矩阵(切子图) × n 卷积核(小特征)
=(点乘)=>
m-n+1 新矩阵(激活值), 步长=1
=(激活函数)=>
m-n+1 新图像矩阵(特征图)
一般把图片和特效图统称为 通道
. 一般卷积核称为为过滤器
. 卷积 即 卷积运算, 即点乘运算.
卷积核要素:
1 通道输入 - 1 通道卷积核 - 1 特征图
每个通道都有独立的卷积核, 每个通道得到各自特征图后进行融合(求和), 最终得到一个融合特征图.
n 通道输入 - n 通道卷积核 - n 通道临时特征图 - 1 通道融合特征图
n 通道输入 - n×n 通道卷积核 - n×n 通道临时特征图 - n 通道融合特征图
卷积后得到的 m 特征图 × n 池化运算(算法,步长)
=(池化算法,求最大值/平均值)=>
m/n 池化矩阵, 步长=池化核 shape
=(通常无激活,或者线性激活)=>
m/n 矩阵
池化要素:
ps: 池化核中没有值, 是一个空框, 算法是计算框中的 max 或 avg.
卷积与池化拥有如下特征
图像平移, 不影响识别位置变化的图像.
全连接神经网络: 输入矩阵 m => 输出矩阵 n, 链接数 m×n, 参数=连接数 × 2 (w,b)
卷积神经网络: 输入矩阵 m × 卷积核 n => 输出激活矩阵(m-n+1), 连接数 n × (m-n+1), 参数=卷积核数 × 2 (w,b)
稀疏链接: 链接数少; 权值共享: 卷积核参数被多条链接共享.
卷积核大小与运算量的关系:
运算量 = 卷积核大小 $n^2$ × 特征图大小 $(m-n+1)^2$ ≈ 在 $m=n$ 时 达到最大
卷积层数叠加产生的效果:
例如 $5×5 =(3×3)=> 3×3 =(3×3)> 1×1$, 说明第二次叠加后 $3×3$ 的卷积核再原图上作用的大小因为层数叠加而放大了.
卷积核大小的选择, 一般使用较小的卷积核, 叠加更多层数, 靠前的网络卷积核大小略大于后面层数的卷积核大小.
为了避免经过多层网络运算后, 特征图逐渐变小, 需要在运算前对图像进行填充. 而且在进行填充后, 也可以更好的利用边界值信息参与运算.
一般情况, 填充内容为 0 或者与边界值相同.
填充 p(padding), 步长 s(stride), 图像大小 i(input), 特征图大小 o(output), 卷积核大小 n
o -> i, p, n, s
例如 1: 4×4 =(3×3)=> 2×2, 这时为了保证输出与输入大小不变, 将原输入图扩充卷积核步长 1 得到新输入 6×6 (4×4 周围扩大一圈 1×1 得到 6×6), 4×4 =(1×1 扩充)=> 6×6 =(3×3)=> 4×4.
例如 2: 4×4 =(5×5)=> 1×1, 这时为了得到原图大小, 需要填充 2 得到 8×8 的输入.
o=math.ceil((i+2p-n)/s)+1
LeCun - LeNet(MNIST) - AlexNet(ImageNet) -
题目, 摘要, 网络结构图
32×32
C
, 卷积F
或 f.maps
, 特征图 6@5×5
S
, 向下采样 (pooling 池化过程)F
, FC
全连接基于 AlexNet 做出的调整, 更灵活适应不同任务
]]>参考: https://www.pypandas.cn/ 或 pandas docs
numpy 主要做计算, pandas 主要做数据清理和分析.
1 | import pandas as pd |
类似 ndarray 只有一列数据, 但是 series 每个数据都有一个 index 标签, 默认是 0 开始序数.
每个元素底层类型是 numpy.int64
1 | dt = pd.Series([1,2,3]) |
DataFrame 是多个 Series 组成的表
1 | # 使用 array 创建 |
1 | # csv json excel xml html hdfs ... |
1 | df.head(n=5) |
1 | # 是否是缺失值 |
1 | # 统计操作 |
1 | # 折线图 |
存储图片
1 | from PIL import Image |
1 | # index 不变, c1 中的值做列, 展示 c2 数据 |
排序
1 | df.sort_values(by = "c", ascending=True) |
替换
1 | df["nc"] = df["c"].replace("regexp", "", regex=True) |
数据类型转换
1 | df["nc"] = pd.to_numeric(df["c"]) |
拼接
1 | # axis=0 上下拼, axis=1 左右拼 |
1 | # 重命名 column 字段 |
参考: https://www.numpy.org.cn/ 或 numpy docs
numpy 是一个 C 实现的计算库, 开源且性能优异, 是众多科学库的依赖
ndarray 向量/线性方程组运算
ndarray 底层是 C 实现, 所以要求数据类型一致
1 | import numpy ad np |
查看函数的使用方法, 鼠标在括号内, Mac 按 Command, Win 按 Alt 查看帮助.
np.zeros(shape)
使用 0 填充np.ones(shape)
使用 1 填充np.empty(shape)
创建但是不赋初始值np.full(shape, value)
使用自定义填充np.arange(count).reshape(shape)
创建一个指定数量的一维数组, 重新改写形状类似的有 ones_like()
, empty_like()
, zeros_like()
, full_like()
使用 ndarray 替代 shape 参数
np.random.randint(low, high, size)
随机整数范围 [low, high)np.random.random(size)
随机浮点数 [0,1)索引(逗号)与切片(冒号)
[:]
指的是该维度上的所有, [...]
表示所有其他维度
使用一维或多维数组做 nd 的下标, 相当于将 nd 的值放到数组的对应位置
a[[1,2,5]]
取 a 中 id 为 1,2,5 的元素组成新 nd,a[[1,2,5]] = [1,1,1]
可以赋值给 nd arraya[[1,2,5]] += 1
可以对 nd array 运算在一维数组 a 中取值 a[x], 在多维数组 b 中取值 b[x, y] 其中 x,y 都是目标形状的数组
值为 True/False 的数组
b = a > 0
所有为真的位置为 Truea[a<0] = 0
将所有 < 0 的标记为 True, 又将下标 True 的值置位 0
list [:]
切片创建指针数据副本(还指向源数据,修改时指向新数据)
nd [:]
切片指向原内存修改原数据改变, nd [id]
索引创建数据副本修改原数据不变
维度不同, 后缘维度轴长相同: (x,y) vs. (y,z)
维度相同, 其中有一个轴为 1: (x,y,1,v) vs. (x,1,u,v)
np.broadcast_to(dt, shape)
根据条件配置进行广播np.expand_dims(dt, axis)
在指定轴上拓展一个长度为 1 的维度np.squeeze(dt)
删除长度为 1 的轴, 降维dt.T
或 np.transpose(dt, axes)
, 默认是将 shape 反过来np.flip(dt, axis)
np.swapaxes(dt, src, tar)
np.rollaxis(dt, id, before)
拼接
np.concatenate((a,b), axis)
指定方向维度拼接np.hstake((a,b))
或 np.r_[a,b]
horizon, row 拼接np.vstake((a,b))
或 np.c_[a,b]
vertical, column 拼接分割
np.split(a, count)
平均切成几段np.split(a, [id, id...])
在指定位置切分成几段np.hsplit(a, count)
row 分割np.vsplit(a, count)
column 分割np.argmax(a)
最大值所在位置np.argmin(a)
最小值所在位置np.where(cond)
符合条件的元素 id 列表np.where(cond, True 填充默认原值, False 填充默认 0)
a[np.where(cond)]
基于条件选择下标1 | dt = np.array() |
配置
指的是配置一些风控维度进行数据监控统计, 查询
指的是基于配置查询用户触发记录, 和 处理开关
在配置和查询之后对有风险的用户进行一定的开关操作.下面详细列举一下各个风控模块的具体内容
风控因子
风控配置修改记录
风控记录信息: 时间, 风控名称, 触发条件, 用户 ID, 触发邮箱/手机号, 风控等级, 风控处理
前面介绍了不同类型的风险因子, 根据不同风险条件的组合, 可以设计出自动化的风控开关, 以便于限制用户的不同行为.
交易所整体的开关, 也可以认为是服务降级, 在出现大规模严重风险时需要降级维护全站或者部分功能, 以便于升级或者排查风险. 用户级别的开关, 用于在某个用户出现风险时对用户的行为限制. 对冲开关是基于用户维度做数据分析后, 将用户分为 AB 仓进行仓位管理的一个方案.
在上面列举不同开关时大致已经明确了不同开关的目的和用途, 这里着重说一下交易和资产划转. 当用户出现问题时, 堵住资金流转过程是最大程度保护用户资产和系统安全的方式. 其中如果如果用户账号被盗, 或者用户盗取其他用户资产, 那么在系统中禁止提币是第一步, 禁止资金在各个系统模块(现货,合约,期权,理财,C2C 等)之间的划转是第二步, 禁止在模块内进行砸盘拉盘交易将资金对敲给其他用户是第三步, 这样可以在一切事情调查清楚之前最大程度保证全站用户的资产安全
]]>市场风险
主要包括: 行情波动, 报价丢失, 项目跑路, 交易所跑路
行情波动的风险, 主要因为消息产生的确定性方向波动, 做市没能快速捕捉消息而造成亏损. 这时候的主要应对方式是在消息放出时间点之前, 降低流动性厚度.
报价丢失主要因为网络问题, 维护, 项目方跑路, 交易所跑路引起, 这时候需要接入多家交易所报价, 用算法去选择报价.
政策风险
主要包括: C2C 商家问题, 出现黑币, 出现黑资金, 在不合法地区展开商业活动, 无牌照
其中 C2C 商家问题需要产品层面设置保证金来解决.
黑币和黑资金问题是技术层面能处理的, 将链上的各种黑客行为菠菜地址加入黑名单, 出现对应的资金直接风控
其他不合法问题, 直接离开不参与.
]]>做市系统风险
主要来源于三部分: 外部市场 API 问题, 做市市场 API 问题, 资产仓位管理
其中 API 问题主要分为公有 API 和私有 API 问题.
公有 API 主要包括: 订单簿,报价,成交单,K 线,成交量等. 外网 API 主要影响报价以及市场数据的分析, 以及做市策略的制定.
私有 API 主要包括: 挂撤单,平仓,资产,仓位. 外网 API 主要影响仓位管理. 内网 API 影响做市效果. 最终都会影响做市盈亏.
流动性风险
主要包括: 仓位过大, 保证金不足, 余额不足, 流动性不足
仓位过大包括总仓位过大, 这时的 A 仓用户仓位都集中在单边, 造成浮动盈亏波动加剧, 内网保证金不足, 余额不足. 也包括外网对冲仓位过大, 也就是 B 仓用户仓位集中在单边, 这时直接引起外网保证金不足, 余额不足.
流动性不足主要是指在内网的流动性厚度超过外网厚度时, B 仓用户开仓造成外网流动性不足以负担内网流动性需求引发交易滑点产生亏损.
关于如何划分 AB 仓用户:
最近在基于机器学习做分类问题, 想着将用户行为数据和交易数据做一个模型训练. 大致参考的维度在之后的 用户行为风险管理
里面的 风险因子
去进一步描述.
关于短期对赌方向的预测:
在基于分钟 K 线上构建机器学习模型, 将常用的 MACD, BOLL, RSI 等指标配合 OHLCV 进行模型构建, 并且定期做模型更新, 进而预测短期市场走向并判断 AB 仓盈亏概率.
]]>风险主要分为以下方面
交易系统风险
: 系统漏洞, 流量攻击, 访问墙, 钱包被盗做市系统风险
: 交易所/做市系统 API 问题(订单簿,报价,成交单,K 线,成交量; 挂撤单,平仓,资产,仓位)流动性风险
: 仓位过大, 保证金不足, 余额不足市场风险
: 行情波动, 报价丢失, 项目跑路, 交易所跑路政策风险
: C2C 商家问题, 出现黑币, 出现黑资金, 在不合法地区展开商业活动, 无牌照用户行为风险
: 刷子用户, 代理商行为, 用户交易行为, 用户交易策略我们主要处理做市系统风险, 流动性风险, 用户行为风险, 市场风险, 以及少量交易系统风险数据, 和政策风险, 其他安全相关的风险由交易所运维和网络安全相关部门.
交易系统风险中, 钱包被盗问题划分到用户行为风险模块中展示(毕竟也算是一种用户的行为). 我们后面分三部分讨论 做市系统风险 & 流动性风险, 市场风险 & 政策风险, 以及用户行为风险.
]]>神经网络结构越复杂, 能解决的问题就越复杂
将输入层数据使用 $z = w_1x_1 + w_2x_2 + … + w_nx_n + b$ (即为 $Z = W^TX+b$) 计算后, 通过激活函数 sgn/logistic/… 等非线性函数转换得出隐藏层 a
$$
\begin{cases}
z=w^Tx+b \
a=f(z) \
\end{cases}
$$
每个隐藏层又作为输入层参与下一层网络的计算.
网络结构为每一层的每个神经元都与下一层的所有神经元相连接.
在已知神经网络上, 传入变量, 得到结果, 就是预测过程.
训练过程(反向传播)
通过反复进行训练过程, 实现参数优化
其中 Lr
为 Learning rate 学习率, 较大时容易在最优解附近跳跃, 较小学习过程漫长.
最终在损失不再下降或者下降的幅度很低时, 或者达到指定学习次数后, 训练完成.
缓存每个节点微分的值, 需要的时候直接取用
$\frac{\partial J}{\partial w^{1}{11}} = \frac{\partial J}{\partial z^{1}{1}} * \frac{\partial z^{1}{1}}{\partial w^{1}{11}}$
$\frac{\partial J}{\partial w^{2}{11}} = \frac{\partial J}{\partial z^{1}{1}} * \frac{\partial z^{1}{1}}{\partial w^{2}{11}}$
在记录了每一层 $\partial z$ 之后, 运算就无需每次从后向前一步步运算.
通过自动微分向前逐步找到前面的 $w$ 值的过程, 成为前向传播.
]]>类定义
1 | class SuperClass(): |
初始化对象
1 | cn = ClassName(name="zs", age=22) |
可管理属性(装饰器): 保留了属性可见性, 增加了 getter 和 setter 的逻辑
1 | class ClassName(): |
__new__
创建对象, __init__
将创建后的对象初始化__eq__
== , __ne__
!= , __ge__
>= , __gt__
> , __le__
<= , __lt__
< , __contains__
in__add__
+-, __mul__
*/, __mod__
%, __rmod__
%, __rmul__
/__len__
, __sizeof__
, __hash__
, __str__
, __repr__
, __format__
,__setattr__
, __getitem__
, __getattribute__
, __delattr__
,__class__
, __doc__
,__getnewargs__
, __getslice__
,__reduce__
, __reduce_ex__
,__subclasshook__
,
线性回归与逻辑回归
卷积神经网络
结果是连续函数, 一般为回归问题; 结果是离散函数, 一般为分类问题.
将模型的输入作为自变量, 输出作为因变量, 构建线性方程 $f(x)=W^TX+b$ (其中 W, X, b 均为向量)
通过训练数据 X->Y
优化线性方程参数 (W,b)
的过程, 即为机器学习.
通过梯度下降优化方程, 找到更优的 (W,b)
使得损失函数(代价函数)最小
$$
J(w,b) = \frac{1}{2} \Sigma^n_{i=1}[(f(x_i) - y_i)^2], \qquad \qquad n 为 样本的特征维度
$$
w
, b
梯度下降: 求 J(w,b)
函数 局部最优解(最小值)的方法
$$w’ = w - \alpha \frac{\partial{J}}{\partial{w}}$$
参考: 什么是梯度和导数 https://zhuanlan.zhihu.com/p/377666441, 什么是梯度下降法 https://www.zhihu.com/question/305638940
梯度
: 对于函数的某个特定点,它的梯度就表示从该点出发,函数值增长最为迅猛的方向.
下降
: 在优化过程中, 梯度 $\nabla{f}$ 的模 $||\nabla{f}||$ 一直在变小
超参数
: 不是模型学习过程中习得的, 而是根据经验设置的.
初始参数, 会影响学习走向不同的局部最优解
目标函数是凸函数, 梯度下降法的解是全局最优解
如何判断/认为收敛
小批量梯度下降, 每个子集称为 batch, 全部子集循环一遍称为 epoch
有 f(x) = WX + b
使得
$$
z =
\begin{cases}
正类, f(x) \ge 0 \
负类, f(x) \lt 0
\end{cases}
$$
因为阶跃函数连续不可导, 所以将其转化为sigmoid函数
$$
h(f(x)) = \frac{1}{1+e^{-f(x)}} \
f(x) = \frac{1}{1+e^{-(wx+b)}}
\begin{cases}
正类, h(f(x)) \ge 0.5 \
负类, h(f(x)) \lt 0.5
\end{cases}
$$
对应的损失函数 J(w,b)
为
$$
J(w,b)_i = - y_i\ln{f(x_i)} - (1-y_i)\ln[1-f(x_i)]
$$
其中 $y_i \in {0,1}$, $f(x_i)$ 正类概率, $1-f(x_i)$ 负类概率; 当 $y_i = 0$ 时, 为负类, 损失函数前半部分为0, 当 $y_i = 1$ 时, 为正类, 损失函数后半部分为0.
$$
J(w,b) = - \frac{1}{m} \sum_{i=1}^m {y_i\ln{f(x_i)} - (1-y_i)\ln[1-f(x_i)]}
$$
参考: 损失函数 II - 逻辑回归 https://towardsdatascience.com/optimization-loss-function-under-the-hood-part-ii-d20a239cde11
]]>1 | if cond: |
1 | while cond: |
1 | for item in str/list/tuple/set/dict/dict.keys()/dict.values()/dict.items(): |
三元操作符: x if cond else y
列表推导式: [expr for item in var]
[x*x for x in range(1,20)
[x*x for x in range(1,20) if x%2 == 0]
[x*x if x%2 == 0 else -x for x in range(1,20)]
[x+y+z for x in "123" for y in "456" for z in "789"]
集合推导式: []
换成 {}
字典推导式: {k: v for xx in yy}
功能的封装, 代码的复用
函数的基本结构
1 | # 空2行 |
返回值, 与返回值 tuple 解构
1 | v = func_name() |
参数的使用: 形参 vs 实参
func(v)
func(k=v)
func(*args)
, args
是元组类型, 调用方法 func(a, b, ..)
或 func(*list)
func(**kwargs)
, kwargs
是字典类型, 调用方法 func{k1=v1, k2=v2, ..}
或 func(*dict)
参数的引用传递
参数传递以引用的方式传递, ps: NodeJS 和 Go 都是值传递, 在传递复杂类型的时候, 传递的是复杂类型指针的值, 实现了引用传递.
作用域
global
提升为全局变量global
提权的情况下修改不对全局变量生效(一旦有修改,就相当于定义了局部变量, 与全局有冲突了)匿名函数 lambda
f = lambda params: expr
eg: sorted(var, key=lambda x: len(x))
eg: iter = map(lambda x: x*x, list/tuple/dict.values())
装饰器函数
1 |
|
1 | # 需要一个wrapper功能 |
深度学习 机器学习 和 人工智能的关系
深度学习(DL) ⊂ 机器学习(ML) ⊂ 人工智能(AI)
什么是机器学习
机器学习即从数据集中, 寻找一个数据关系函数: 训练数据集-优化模型函数-完成新的任务
入门机器学习任务都有哪些例子
样本, 特征, 特征向量, 特征维度, 类别, 类别标签
手写数字识别中
训练集
: 拟合找到函数; 1000 个测试图 测试集
: 判断函数优劣样本
特征
, 784 个点叫 特征维度
, 784 个 0-255 的数字构成一个向量为 特征向量
, 特征向量中点在空间中的分布叫 特征空间
类别
, 0-9 每个数字都是一个 类别标签
关于 TPE
任务分类 Task T
都有哪些种分类
簇
分类性能度量 Performance P
的方法有哪些
经验观测 Experience E
范式
学习算法从数据集中获取经验 -> 优化函数系数
误差
误差: 函数结果与实际结果的距离
训练误差: 训练数据集
测试误差: 测试数据集
泛化能力: 未知数据集
容量: 模拟拟合能力的大小
过拟合: 训练数据集上训练多了, 实际测试数据集表现不好
欠拟合: 训练数据集上训练不够
过拟合/欠拟合的原因: 当前 模型参数容量 与 问题难度, 任务复杂程度 不匹配.
训练误差 | 测试误差 | 原因 |
---|---|---|
小 | 小 | 泛化能力强(\(^o^)/~ 目标) |
小 | 大 | 过拟合 |
大 | 大 | 欠拟合 |
大 | 小 | 不可能出现 |
模型的选择方法
假设
与经验观测
一致, 选择最简单的那个(模型容量最低的)数据集的划分方法
m
个样本的 数据集 D
, 随机取样放入 训练集 D'
后放回(有放回), 重复 m 次得到含有 m 个样本的新 训练集 D'
(大小为 m, 数据有重复), 那么测试集为 D - D'
, 适合小样本: 参考: https://blog.csdn.net/sdf57/article/details/119063276模型的评价方法
回归问题
sum(pow(delta Y, 2)) / N
- 更好的求导sum(abs(delta Y))) / N
分类问题
混淆矩阵: 正类 P, 负类 N; 预测正确 T, 预测错误 F
真实值\预测值 | 1 | 0 |
---|---|---|
1 | TP 正确预测正类 | FN 错误预测正类 |
0 | FP 错误预测反类 | TN 正确预测反类 |
参考: 混淆矩阵 Confusion Matrix https://blog.csdn.net/seagal890/article/details/105059498
预测值 (预测区间) vs 置信度 (置信区间): https://zhuanlan.zhihu.com/p/366307027
P-R 曲线图
, 查准率和查全率 在采样不同置信度时 彼此矛盾, 曲线下方面积记为 AP值
, AP 值越大可以表示模型表现越好. 但是这个值不太好求得, 但是当 P=R 时, 查全率和查准率都比较高, 这个点记为的平衡点, 该点的调和平均值记为 F1 分数:
F1 = 2*P*R/(P+R) = 2*TP / (|D| + TP -TN)
, 其中 D 为数据集中样本总量参考: 机器学习中 F1 分数的简介与计算 https://www.v7labs.com/blog/f1-score-guide
参考书籍
没有免费午餐定理
没有免费的午餐定理(No Free Lunch,简称 NFL). 如果不对特征空间有先验假设, 则所有算法的平均表现是一样的.
我们认为: 特征差距较小的样本更有可能是同一类. 但是这一定是对的么? 比如火鸡理论.
数据类型参考: https://www.geeksforgeeks.org/python-data-types/?ref=lbp
基础数据类型包括:
[]
, tuple ()
){k:v}
{}
类型判断:
type() 判断类型
isinstance() 判断类型是否属于指定类型
id() 判断底层是否是一个目标
hash() 计算哈希值
dir(obj) 查看类型支持的方法
类型转化:
数据类型转换, 参考: https://cloud.tencent.com/developer/article/1945472
输出格式化:
类型格式化符号, 参考: https://python-course.eu/python-tutorial/formatted-output.php
使用 print("字符串" % (变量tuple))
格式化 %[flags][width][.precision]type
d
或 i
整型f
浮点c
字符r
或 s
字符串参考: https://www.runoob.com/python3/python3-number.html
1000 以下的整型数字, 是不基于引用计数销毁的, 所有 1000 以下数字的变量都指向相同目标
运算有 +
, -
, *
, /
除, //
整除, %
取余, **
求幂(与 pow 函数相同)
除法不判断 0 会有 ZeroDivisionError 问题
整型有无限长度, 限制是电脑支持的上限
与 NodeJS 类似, or 都是懒惰判断
本质上 True => 1, False => 0
反过来判断为 False 的有 0
, 0.0
, ""
, []
, {}
, ()
Python允许连续判断: a<b<c
, 连续赋值 a=b=c=1
优先级 not > and > or
+
, 重复 *
in
, not in
[]
[:]
len()
参考: https://www.runoob.com/python3/python3-string.html
Unicode 编码的不可变序列
单引号, 双引号, 三引号均可. 三引号可以编写跨行字符串, 注释.
"_".join(["a","b","c"])
"xx".split(" ")
[]
参考: https://www.runoob.com/python3/python3-list.html
类型不统一的可变序列
L.append(item)
del L[id]
或 L.remove(v)
L[id] = v
L[id]
L.sort(reverse=False)
inline正序, sorted(L)
不影响原列表返回排序好的新列表()
参考: https://www.runoob.com/python3/python3-tuple.html
类型不统一的不可变序列, 只允许查询.
参考: https://www.runoob.com/python3/python3-dictionary.html
字典: {k:v}
结构的无序可变键值对, k 必须是不可变对象(可hash哈希的): str, bool, int, float, tuple.
可以使用 map() 将 [[k,v], ...]
, [(k,v), ...]
, ["kv", ...]
转化为字典
增/改: d[k] = v
删: del d[k]
或 v = d.pop(k)
查: d[k]
清空: d.clear()
, 字典还在变成空字典
删除: del d
, 字典删除不存在了
键: d.keys()
值: d.values()
键值对: d.items()
参考: https://www.runoob.com/python3/python3-set.html
集合: {}
无序数据集. 支持交并差补.
可变集合 Set:
增: s.add(x)
删: s.remove(x)
不存在报错, s.discard(x)
不存在不报错, s.pop()
随机删除
改: s.update(x, y)
清空: d.clear()
, 字典还在变成空字典
成员关系: in
, not in
判断元素是否在集合中
集合关系: ==
, !=
, >
, >=
, <
, <=
判断是否是子集
交集 &
, &=
并且
并集 |
, |=
或
差集 -
, -=
减
补集 ^
, ^=
异或
不可变集合 FrozenSet: 不能做增删修改操作
]]>