wenmo8 发布的文章

目前,在软件开发的协作中,
Git
无疑是版本控制的王者。

而其中的
git log
命令,犹如一把强大的历史探寻之剑,能够帮助我们深入洞察项目的演进历程。

本篇将为大家整理解读几个实用的
git Log
技巧,让你的项目管理和代码审查工作如虎添翼。

1. 挖掘代码深处的历史变更

git log
具备
按文件内容搜索提交
的强大功能。

使用
git log -S "字符串"
命令,我们可以搜索提交历史中添加了特定字符串的提交(默认区分大小写)。

比如,我想看看我的代码中何时添加了
class FadeVideo
,可以使用如下命令:

$  git log -S 'class FadeVideo'
commit 045447e05a735850fe7eb8274d95f7499042fe98 (HEAD -> master, origin/master, origin/HEAD)
Author: wangyubin <linuxr@aliyun.com>
Date:   Fri Dec 20 16:50:30 2024 +0800

    add animations video fade

如果想要不区分大小写进行搜索,可以添加
-i
选项。

$  git log -i -S 'class fadevideo'
commit 045447e05a735850fe7eb8274d95f7499042fe98 (HEAD -> master, origin/master, origin/HEAD)
Author: wangyubin <linuxr@aliyun.com>
Date:   Fri Dec 20 16:50:30 2024 +0800

    add animations video fade

$  git log -S 'class fadevideo' # 没有-i选项,搜索不到结果

结合 -p 选项,还能同时查看这些提交的差异变化。

$  git log -i -S 'class fadevideo' -p
commit 045447e05a735850fe7eb8274d95f7499042fe98 (HEAD -> master, origin/master, origin/HEAD)
Author: wangyubin <linuxr@aliyun.com>
Date:   Fri Dec 20 16:50:30 2024 +0800

    add animations video fade

diff --git a/short_videos/animations/fade.py b/short_videos/animations/fade.py
new file mode 100644
index 0000000..e924471
--- /dev/null
+++ b/short_videos/animations/fade.py
@@ -0,0 +1,268 @@
+titles = [
+    "基本使用",
+    "FadeIn的shift参数",
+    "FadeIn的target_position参数",
+    "FadeOut的scale参数",
+]
+codes = [
+    """# 创建一个圆形

这在我们想要追溯某个特定代码片段或函数是在何时被引入项目,以及在后续提交中如何被修改时,发挥着不可替代的作用,能够帮助我们深入理解代码的演变逻辑。

2. 深入代码差异的提交详情

仅仅知道提交的存在是不够的,很多时候我们需要了解每次提交到底对代码做了哪些具体的更改。

git log -p
命令在显示提交日志的同时,还会展示每次提交所带来的差异变化。

$  git log -p
commit 045447e05a735850fe7eb8274d95f7499042fe98 (HEAD -> master, origin/master, origin/HEAD)
Author: wangyubin <linuxr@aliyun.com>
Date:   Fri Dec 20 16:50:30 2024 +0800

    add animations video fade

diff --git a/main.py b/main.py
index e15c8a1..e340db1 100644
--- a/main.py
+++ b/main.py
@@ -59,6 +59,7 @@ def animations_help():
     params = {
         "text": "文字的创建与销毁",
         "graph": "图形的创建与销毁",
+        "fade": "淡入淡出",
     }

这对于代码审查、问题排查以及理解项目功能的逐步演进至关重要。

比如,当发现某个功能出现异常时,通过
git log -p
查看相关提交的差异,能够快速定位到是哪个提交引入了问题,以及具体的代码改动之处,从而高效地进行修复。

3. 对比分支开发进度

在多人协作开发或者多分支并行开发的场景下,经常需要比较不同分支之间的差异。

git log master..develop
命令就可以显示
develop
分支中存在但
master
分支中不存在的提交。

这在准备将某个分支的功能合并到主分支之前,或者想要了解不同分支的开发进度差异时非常有用。

比如,下面我的一个项目,比较其中两个分支的区别:

$  git branch
* collector
  develop
  master

$  git log develop..collector
commit ee035a3ed6aa71d8650d4dc823be6a6045894e11 (HEAD -> collector, origin/collector)
Author: wangyubin <linuxr@aliyun.com>
Date:   Sun Dec 1 10:11:11 2024 +0800

    use poltly to display kline

commit d8b65fad3beca572fa1e7d57fa90e5c9345e575f
Author: wangyubin <linuxr@aliyun.com>
Date:   Sat Nov 30 00:55:49 2024 +0800

    update kline utils

4. 简洁至上的提交概览

在查看项目提交历史时,有时候我们不需要冗长的详细信息,只希望快速了解每个提交的大致情况。

git log --oneline
就完美地满足了这一需求。它将每个提交压缩成一行,仅仅展示简短的提交哈希和提交消息。

这样一来,我们能够在有限的屏幕空间内迅速扫视众多提交,把握项目的主要更新脉络。

$  git log --oneline
ee035a3 (HEAD -> collector, origin/collector) use poltly to display kline
d8b65fa update kline utils
f3d749a update K线显示
540e2ef add k线查看
efaf17e update readme
30e672d add coin info utils
35cdd3e fix 数据采集改造后的错误
03f1626 fix 配置文件加载错误
a7e5c42 rework collector
5d69716 fix binance collector start time
8503533 rework binance collector
59cc2b6 add uv project manager
1f29fbf update binance api
924545c update 整体结构
... ...

5. 追踪特定文件的变更轨迹

当我们重点关注某个或某些文件的历史变化时,通过
git log <filename>
的形式,我们可以过滤出对指定文件进行更改的提交。

如果需要同时查看多个文件的提交历史,只需像
git log file1 file2 file3
这样传递多个文件名即可。

$  git log .\config.py
commit 30e672d3e78c9fbc6198373940a464b8132a9b06
Author: wangyubin <linuxr@aliyun.com>
Date:   Thu Nov 7 18:01:54 2024 +0800

    add coin info utils

commit a7e5c4271cad314460a1793c8c62aa93acd70077
Author: wangyubin <linuxr@aliyun.com>
Date:   Tue Oct 29 11:57:20 2024 +0800

    rework collector

commit 5d697169b687ea02ad4723e74fbc3052e033a6c4
Author: wangyubin <linuxr@aliyun.com>
Date:   Tue Oct 29 11:33:37 2024 +0800

    fix binance collector start time

6. 基于关键字的提交搜索

有时候,我们只记得提交消息中的某个关键字或短语,想要快速找到相关的提交。

使用
git log --grep="模式"
可以按照指定模式(默认区分大小写)过滤提交,

如果不希望区分大小写,可以使用
git log -i --grep="模式"

这在项目规模较大,提交数量众多的情况下,能够帮助我们迅速定位到与特定任务、功能或问题相关的提交记录,极大地提高了代码查找和问题追溯的速度。

$  git log --grep "数据采集"
commit 35cdd3e75933c1a99431ea86d0625faff49f1c16
Author: wangyubin <linuxr@aliyun.com>
Date:   Thu Oct 31 14:41:46 2024 +0800

    fix 数据采集改造后的错误

commit 7edf14cf0cc4478d422dd752d32de146bedefa6f
Author: wangyubin <linuxr@aliyun.com>
Date:   Mon May 27 10:12:08 2024 +0800

    update 数据采集

7. 聚焦特定开发者的工作成果

在团队协作开发中,了解每个成员的贡献情况是非常有意义的。

git log --author="作者名"
命令允许我们按照作者来过滤提交。

git 在此处是按照正则表达式模式进行过滤的,这意味着不需要精确的名称匹配,也不区分大小写。

$  git log --author="linuxr"
commit ee035a3ed6aa71d8650d4dc823be6a6045894e11 (HEAD -> collector, origin/collector)
Author: wangyubin <linuxr@aliyun.com>
Date:   Sun Dec 1 10:11:11 2024 +0800

    use poltly to display kline

commit d8b65fad3beca572fa1e7d57fa90e5c9345e575f
Author: wangyubin <linuxr@aliyun.com>
Date:   Sat Nov 30 00:55:49 2024 +0800

    update kline utils

commit f3d749a335c91385cd6443572a0e5082d05734d1
Author: wangyubin <linuxr@aliyun.com>
Date:   Fri Nov 29 18:51:41 2024 +0800

    update K线显示

... ...

8. 突出项目的合并节点

在复杂的项目开发中,分支合并是常见的操作。

git log --merges
命令能够让我们专注于查看当前分支中的合并提交。

这些合并提交往往代表着不同分支开发成果的整合,对于理解项目的整体架构整合和功能合并过程具有重要意义。

$  git log --merges
commit 97078ccd1545a4d5dc73eac4f92487607ee93010 (origin/master, master)
Merge: 49a457c e49da8b
Author: wangyubin <linuxr@aliyun.com>
Date:   Sun Oct 13 20:50:34 2024 +0800

    Merge branch 'master' of gitee.com:wangyubin/b_st_middle

commit b29438b16351552a54c8e4fbe477154059d2dcd5
Merge: 9e4a212 366875c
Author: wangyubin <linuxr@aliyun.com>
Date:   Mon May 27 10:52:28 2024 +0800

    Merge branch 'master' of gitee.com:wangyubin/b_st_middle

9. 精准定位特定时段的变更

在项目开发过程中,我们常常需要关注特定时间段内的代码改动,
git log
提供了强大的时间过滤功能。

比如,当我们想要查看 2024 年 6 月 1 日之后的提交时,可以使用
git log --after="2024-06-01"
命令。

若要进一步缩小范围,查看 2024 年 6 月 1 日至 6 月 25 日之间的提交,只需执行
git log --after="2024-06-01" --before="2024-06-25"

而且,它还支持诸如 "
yesterday
"、"
today
"、"
10 day ago
" 等便捷的日期格式,这使得我们能够根据实际需求灵活地筛选出所需时间段的提交记录。

$  git log --after="2024-06-01" --before="2024-06-25" --oneline
ff5b0b1 add example single string math tex
f3aba71 优化一些场景的切换
f1ca6c7 add integer video
c3a407f 生成视频的结构
db02c64 add main for videos
3358093 add bulleted list example
dd48bd1 add title example
bb3e513 add infra and end page
e36946a add integer example

$  git log --after "10 days ago" --oneline
045447e (HEAD -> master, origin/master, origin/HEAD) add animations video fade
22a0d9f add animations rotate example
f05b8d1 add animation graph video
2664733 add animations graph video
93cf0cf add animation indication example
d9bab37 add animations video text
9462253 add animation grow example
784d4f9 add video Polyhedron
c372485 add animation fade example

10. 个性化的提交展示

最后一个技巧是关于自定义
git log
的日志消息格式。

使用
git log --pretty=format:"格式字符串"
,我们可以根据自己的需求灵活定制日志的显示格式。

比如,
git log --pretty=format:"%Cred%an - %ar%n %Cblue %h -%Cgreen %s %n"

通过这种方式,我们可以选择显示提交作者、提交时间、提交哈希以及提交消息等不同的信息,并对其进行颜色标记等格式化处理,使日志信息更加清晰易读,满足不同场景下对提交信息展示的个性化要求。

11. 总结

git log的参数其实有很多,参考:
https://git-scm.com/docs/git-log

本篇只是总结了一些平时使用的几个技巧,如果大家有其他更好的查看日志的技巧,欢迎交流。

【银河麒麟系统图示化黑屏进不去输入不了任何字】

**问题描述:
黑屏

logo之后黑屏

浪潮售后

麒麟售后
都是踢皮球的 没啥用

解决问题: 长篇短说

  • 现在不是 输入不了 任何东西吗
  • 记住IP地址 然后拿一台笔记本 ssh连接到这台服务器
  • 进去之后 输入命令
  • startx #前台运行(不推荐)
  • nohup startx & #后台运行(推荐)
  • 等待一会 即可 进入图示化界面

如果你不知道IP 无法连接ssh的话

去浏览器 或者 AI 搜索Linux 图示化模式 怎么变成命令行模式

在一些常见的桌面环境中,如 GNOME 和 KDE,你可以使用 “Ctrl + Alt + F1 - F6” 组合键来切换到不同的虚拟控制台(tty),这些虚拟控制台默认是命令行模式。其中 “F1 - F6” 表示不同的控制台编号,一般来说 “F1” 对应的控制台可以用于登录并进入命令行操作。要返回图形界面,可以使用 “Ctrl + Alt + F7 - F12”(不同的发行版和桌面环境可能有所不同)。

如果对你有用 点个赞呗ovo 嘿嘿!!!
不懂的可以私信我哦!!!
我要是懂得话 就会跟你说哦!!!

这是小卷对分布式系统架构学习的第5篇文章,今天来学习限流器和限流设计模式

1.为什么要限流?

任何一个系统的运算、存储、网络资源都不是无限的,当系统资源不足以支撑外部超过预期的突发流量时,就应该要有取舍,建立面对超额流量自我保护的机制,而这个机制就是微服务中常说的“限流”

2.四种限流设计模式

说到限流,大家直接的想法就是Sentinel,但是Sentinel限流的原理可能很多人没去深入理解,或者限流到底是怎么做的?具体如何进行限流,业界内也有一些常见设计模式。

2.1流量计数器模式

流量计数器是一种最简单的限流方式,通过记录固定时间窗口内的请求次数来判断是否达到限流阈值。如果请求次数超过限制值,则拒绝后续请求。

实现方式:

  • 将时间划分为固定的时间窗口(如 1 秒、1 分钟)。

  • 每个窗口维护一个计数器,记录当前时间窗口内的请求次数。

  • 如果计数器值超过限流阈值,直接拒绝请求;否则增加计数器。

固定窗口边界问题:

  • 在窗口边界的两端,可能存在短时间内超量请求的“
    临界问题

比如场景设定:一秒内的TPS大于80时,就限流。

存在问题:即使每一秒的统计流量都没有超过 80 TPS,也不能说明系统没有遇到过大于 80 TPS 的流量压力。比如说系统在连续2秒内都收到60TPS的请求,但是请求发生的时间分别在第1秒的后0.5秒,以及第2秒的前0.5秒。这样系统实际曾在1秒内发生超过80 TPS的请求。

  • 即使连续若干秒统计流量超过阈值,也不能说明流量压力一定超过系统承受能力

假设 10 秒的时间片段中,前 3 秒的 TPS 平均值到了 100,而后 7 秒的平均值是 30 左右,此时系统是否能够处理完这些请求而不产生超时失败?答案是可以的

存在缺陷
:造成上面2个问题得原因是流量计数器模式是对时间点进行离散的统计

2.2滑动窗口模式

概念:时间轴上,一个固定大小的窗口随时间平滑滚动。任何时刻,静态地通过窗口内观察到的信息,都等价于一段长度与窗口大小相等的信息。
主要是通过记录多个较小时间窗口(子窗口)的请求次数,实现更精细化的限流控制

假设:准备观察的时间片段为 10 秒,以 1 秒作为统计精度,那可以得到一个长度为 10 的数组。设定限流阈值是最近 10 秒内收到的请求不超过 500 个,那么就需要统计10个子数组的请求总数,是否超过阈值。

优点

  • 解决了固定窗口边界问题

缺点

  • 只适用于否决式限流,超过阈值的流量就必须失败

2.3漏桶模式

漏桶可以简单的理解:小学水池应用题,一个水池,每秒以 X 升速度注水,同时又以 Y 升速度出水,问水池啥时候装满。

概念
:将请求视为流入漏桶的水,漏桶以固定速率“漏水”。当请求流量超过漏桶的处理能力时,多余的请求会被丢弃或排队。其核心思想是
平滑请求流量

实现方式

  1. 维护一个队列(或计数器),用来模拟漏桶。

  2. 新请求到来时,将请求放入桶中。

  3. 按固定速率处理桶中的请求。

  4. 如果桶已满,则拒绝新请求。

缺点:

  • 比较难确定桶的大小和水流出的速度

2.4令牌桶算法

和漏桶一样是基于缓冲区的限流算法,简单理解就是去银行办事时在排队机号取号的场景。

概念
:通过固定速率向桶中添加令牌,请求到来时需要先消耗令牌才能被处理。如果桶中没有足够的令牌,请求会被拒绝。与漏桶算法不同,令牌桶允许一定的
突发流量

实现方式

  1. 维护一个桶,桶中存储令牌。
  2. 按固定速率(比如限流是1秒100次请求,那么间隔10ms时间放入令牌)向桶中添加令牌,直到桶满为止。
  3. 请求到来时从桶中取出令牌,如果没有令牌就马上失败或者进入降级逻辑。

实际开发的时候,不需要专门做放令牌到桶里这件事,只需要在获取令牌前,比较一下时间戳与当前时间,就能算出需要放入多少令牌,下面是示例代码:

private long lastTime = System.currentTimeMillis();
private int tokens = 0; // 当前令牌数
private static final int LIMIT = 100; // 桶容量
private static final int REFILL_RATE = 10; // 令牌添加速率(令牌/秒)

public synchronized boolean tryAcquire() {
    long now = System.currentTimeMillis();
    // 添加令牌
    tokens = Math.min(LIMIT, tokens + (int) ((now - lastTime) / 1000) * REFILL_RATE);
    lastTime = now;

    if (tokens > 0) {
        tokens--;
        return true;
    }
    return false;
}

3.分布式限流

上面介绍的4种限流算法都只适用于单机限流,或者把系统当做整体来限流。实际应用中仍然需要精细的每个服务的限流。

概念
:过将限流逻辑分散到多个节点,同时使用一致性算法保证全局限流的一致性。它结合了本地限流和集中式限流的优点。

实现方式

  • 基于 Redis + Lua 脚本
    • 使用 Redis 脚本实现分布式限流,在 Redis 中存储全局的请求计数器
  • 基于一致性算法
    • 使用分布式一致性算法(如 Raft、Paxos)维护全局流量状态
  • 分布式网关
    • 通过 API 网关(如 Kong、Nginx、Spring Cloud Gateway)实现流量的统一调度和限流。

缺点

  • 实现复杂度高,且网络通信和一致性操作带来额外延迟。当流量大时,限流本身会降低系统处理能力

总结

今天学习了4种限流设计模式:流量计数器模式、滑动窗口模式、漏桶模式、令牌桶模式,后面2种都是基于缓冲区的限流算法。简单了解了下分布式限流的概念。限流本身是有代价的,实际开发中需要权衡方案的代价和收益。后续有时间补充Sentinel的限流原理和其中用了哪些设计模式。

本文是高级前端加解密与验签实战的第7篇文章,本系列文章实验靶场为Yakit里自带的Vulinbox靶场,本文讲述的是绕过请求包和响应包加密来爆破登录界面。

分析

这里的公私钥同上文一样是通过服务端获取

通过查看响应包可以看到,data字段被加密了,当然这里我已经知道了data字段和origin字段的内容是一样的,下面来看看该如何编写热加载代码吧。

热加载

方法1(固定私钥)

这里跟上文一样选择Web Fuzzer的序列功能。

数据提取器提取公私钥

由于
afterRequest
函数无法获取到参数,所以在代码里写死了私钥内容来解密响应包。

热加载代码:

var PRIVATE_KEY = `这里填私钥内容(可换行)`

decryptData = (packet) => {
    body = poc.GetHTTPPacketBody(packet) // 获取响应包体
    jsonBody = json.loads(body) // 转为map格式

    //解密数据
    data = codec.DecodeBase64(json.loads(body).data)~
    data = codec.RSADecryptWithOAEP(PRIVATE_KEY/*type: bytes*/, data/*type: any*/)~
    data = string(data)

    // 使用JsonPath定位,替换json中的data
    body = json.ReplaceAll(jsonBody, "$..data", data)
    // 转为json格式
    body = json.dumps(body, json.withIndent("   "))
    // 替换正则匹配结果(可省略)
    pattern := `\\`
    body = re.ReplaceAll(body, pattern, "")

    return poc.ReplaceBody(packet, body/*type: bytes*/, false/*type: bool*/)
}

encryptData = (pemPublic, data) => {
    data = codec.RSAEncryptWithOAEP(pemPublic /*type: []byte*/, data)~
    data = codec.EncodeBase64(data)
    body = f`{"data":"${data}"}`
    return body
}

//分割参数的函数
splitParams = (params) => {
    pairs := params.SplitN("|", 2)
    return encryptData(pairs[0], pairs[1])
}

// 修改响应包
afterRequest = func(rsp){
    return decryptData(rsp)
}

请求格式:

POST /crypto/js/rsa/fromserver/response HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json

{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"admin23","age":"20"})}}

下图为效果图,响应包的data字段的值被解密后的数据替换。

方法2(使用mirrorHTTPFlow)

在这一关(响应加密)和下一关(RSA加密AES密钥)解密过程中,我一直都在寻找如何才能把数据提取器提取到的
privateKey
传参到
beforeRequest

afterRequest
这类函数中,以达到修改数据包的目的。

从前端验签与加解密学习Yakit中WebFuzzer热加载
。在这篇文章中学到了可以使用序列,将前两个序列提取到的key和数据,在第三个序列当做请求内容,解密后发送过去,这样也算是一种变相的完成了解密,但是这个方法感觉不太优雅,需要多一个额外的请求包。

这是当时测试的图片:

然后在 Yak Project官方公众号的
文章
中终于看到了一个函数,
mirrorHTTPFlow
可以解决这个问题,虽然不能直接替换响应包,但会出现在提取数据中。由于官方文档没有具体讲解这个函数,所以它的具体功能现在还不太清楚。

热加载代码:

//加密函数
encrypt = (pemPublic, data) => {
    data = codec.RSAEncryptWithOAEP(pemPublic /*type: []byte*/, data)~
    data = codec.EncodeBase64(data)
    body = f`{"data":"${data}"}`
    return body
}

//分割参数的函数
splitParams = (params) => {
    pairs := params.SplitN("|", 2)
    return encrypt(pairs[0], pairs[1])
}

mirrorHTTPFlow = (req, rsp, params) => {
    // 获取私钥以解密响应数据
    pem = params.privateKey
    
    // 切割响应中的数据,作为 JSON 加载
    _, body = poc.Split(rsp)
    body = json.loads(body)
    
    // 解密data
    data = codec.DecodeBase64(body.data)~
    data = codec.RSADecryptWithOAEP(pem, data)~
    
    return string(data)
}

请求包格式:

POST /crypto/js/rsa/fromserver/response HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json

{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"123","age":"20"})}}

效果如下图,可以看到解密后的data出现在了提取内容中。

爆破成功,但是看不到请求的原始密码,由于太累了懒得解决这个问题,啥时候闲了再说吧。

相关:

https://colab.research.google.com/github/google/brax/blob/main/notebooks/training_torch.ipynb



之前写过一篇同主题的文章,后来发现这个文章中有一些问题,不过也有些不好改动,于是就新开一篇来进行更正和补充!!!

之前版本:

https://www.cnblogs.com/xyz/p/18564777

之所以之前版本有一些问题,其主要原因是其中的很多推理都是使用ChatGPT完成的,后来又遇到其他关于log_det_jacobian的算法,于是就重新遇到了相关问题,这时候通过查看相关资料发现ChatGPT的生成的理论推理有一些问题,但是出现的问题又十分不好察觉,于是就有了本篇。



要想知道log_det_jacobian是个什么东西,首先需要知道Bijector是什么。

给出
https://gowrishankar.info/blog/bijectors-of-tensorflow-probability-a-guide-to-understand-the-motivation-and-mathematical-intuition-behind-them/
的解释:

A bijector is a function of a tensor and its utility is to transform one distribution to another distribution. Bijectors bring determinism to the randomness of a distribution where the distribution by itself is a source of stochasticity. For example, If you want a log density of distribution, we can start with a Gaussian distribution and do log transform using bijector functions. Why do we need such transformations, the real world is full of randomness and probabilistic machine learning establishes a formalism for reasoning under uncertainty. i.e A prediction that outputs a single variable is not sufficient but has to quantify the uncertainty to bring in model confidence. Then to sample complex random variables that get closer to the randomness of nature, we seek the help of bijective functions.


简单来说就是对一个分布进行变换,比如X服从高斯分布,y=tanh(x),那么Y服从什么分布呢,Y的概率密度如何计算,Y分布如何抽样,可以说Bijector就是指分布的变换,而log_det_jacobian就是在分布变换时计算概率密度所需要用到的。

image


各个深度学习框架都针对机器学习中的这种概率分布变换的Bijector提供单独的计算方法,如:

paddle中的:

paddle.distribution.Transform

相关:

https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/distribution/Transform_en.html

image

image


mindspore中的:

mindspore.nn.probability.distribution.TransformedDistribution

相关:

https://www.mindspore.cn/docs/zh-CN/r2.1/api_python/nn_probability/mindspore.nn.probability.distribution.TransformedDistribution.html

image

image

image



概率分布的仿射变换(Bijector)后的概率计算:

image




log_det_jacobian = 2 * (math.log(2) - dist - F.softplus(-2 * dist))

= log( tanh'(x) )


关于tanh函数的特性:

image

image

image

下图来自:

image



高斯函数的信息熵求解公式:

image


各个深度学习框架中的Probability模块的
不足之处

可以说在这个领域TensorFlow Probability (TFP)是最为功能强大和全面的,也是最为公认和广泛使用的,虽然我不喜欢用TensorFlow搞deep learning,但是必须要承认搞probability的深度学习的话还是用这个TensorFlow的TFP貌似更稳妥。

虽然Probability模块的可以自动实现分布变换后的概率密度,采样(sample),logP的计算,但是对于一些其他的计算其实支持并不是很好,如信息熵的计算,因为比如像信息熵这样的计算并不能由Probability模块自动获得,而是需要人为的设置,比如高斯分布的信息熵,这个就是需要人为手动的为不同的分布进行计算,因此可以说Probability模块并不能解决所有的分布变换后的新的统计量的计算,还是有一些需要手动推导计算公式并进行硬编码的,也或者是采用其他的近似的计算方法来解决。


相关:

TensorFlow推荐器和TensorFlow概率:使用TensorFlow概率进行概率建模简介

标准化流(Normalizing Flow)教程(一)