博客

  • 深度学习的可解释性问题

    深度学习,作为人工智能的一种重要技术,已经在各个领域取得了显著的成果。深度学习具有极强的表征学习能力,可以极大降低特征工程的要求。而特征工程由取决于业务理解,在深度学习出现前,谁的模型效果好更多取决于谁的特征选的好。所以在深度学习时代,谁的数据多,模型训练快,就有更好的模型效果。

    深度学习自身的优势带来了大量的业务场景的迭代和更新,但是模型的可解释性也非常重要,特别是对于一些特殊业务,比如风控、金融、医疗等。

    深度学习的可解释性问题,简单来说,就是我们难以理解和解释深度学习模型的决策过程和原理。这是因为深度学习模型通常由数百万甚至数十亿的参数构成,这些参数通过复杂的数学运算相互作用,形成了模型的决策过程。这种过程对于人类来说是难以理解的,因此,深度学习模型被称为“黑箱”。

    深度学习的可解释性问题对其应用产生了一定的影响,从业务上对于可解释性的诉求主要来自三个方面:

    • 模型改进
    • 模型透明度和可信性
    • 模型识别和偏差防止

    提高深度学习可解释性的方法

    1. 特征可视化

    特征可视化是一种常用的方法,它通过可视化神经网络的中间层来理解模型是如何识别和处理输入的。针对不同的中间层,它的效果也是不同的。

    比如卷积核可视化是一种找到使某个卷积核输出最大的图像,从而理解该卷积核关注的特征的方法。这种方法可以帮助我们理解模型的卷积层是如何提取输入数据的特征的。

    2. 模型敏感性分析

    模型敏感性分析是另一种常用的方法,它通过改变输入并观察输出的变化来理解模型对输入的敏感性。例如,我们可以通过添加噪声或者移除某些特征,然后观察模型的输出是否发生变化,以此来理解哪些特征对模型的预测最重要。

    3. 局部可解释模型

    局部可解释模型(LIME)是一种可以解释任何机器学习模型的方法。它通过在输入空间中采样,并在这些点上训练一个简单的模型(如线性模型),来近似原始模型的行为。然后,我们可以通过解释这个简单模型来理解原始模型的行为。

    4. 深度学习解释器

    深度学习解释器(如SHAP,DeepLIFT等)是一种可以量化每个特征对模型输出的贡献的方法。这些方法可以帮助我们理解哪些特征对模型的预测最重要,从而提高模型的可解释性。

    5. 神经网络剪枝

    神经网络剪枝是一种可以简化模型的方法,它通过移除不重要的神经元或者连接来减少模型的复杂性。这样可以使模型更容易理解,从而提高其可解释性。…

  • OpenRewrite和Spring Boot Migrator

    OpenRewrite

    OpenRewrite是一个开源的代码重写工具,旨在帮助开发人员进行大规模的代码重构和迁移。它提供了一个强大的规则引擎,可以根据自定义规则来修改代码,并支持多种编程语言和框架。

    功能特点

    代码重构:OpenRewrite可以自动识别和应用各种代码重构模式,如重命名变量、提取方法、内联方法等,以提高代码质量和可维护性。

    代码迁移:OpenRewrite可以帮助开发人员将代码从一种编程语言或框架迁移到另一种,例如从Java 8迁移到Java 11,或从Spring MVC迁移到Spring Boot。

    规则引擎:OpenRewrite提供了一个灵活的规则引擎,开发人员可以根据自己的需求定义和应用代码重写规则。这使得OpenRewrite非常适合于定制化的代码重构和迁移任务。

    IDE集成:OpenRewrite可以与常见的集成开发环境(IDE)集成,如IntelliJ IDEA和Eclipse,以便开发人员可以在开发过程中直接使用它。


    应用场景

    代码重构:当代码质量下降、可维护性变差或存在性能问题时,开发人员可以使用OpenRewrite来自动化执行各种代码重构操作,以改进代码质量和可读性。

    代码迁移:当需要将代码从一种编程语言或框架迁移到另一种时,OpenRewrite可以帮助开发人员自动执行大部分迁移工作,减少手动修改的工作量和错误率。

    规则定制:开发人员可以根据自己的需求定义和应用代码重写规则,以满足特定的重构或迁移需求。

    Spring Boot Migrator

    Spring Boot Migrator是一个用于升级和迁移Spring Boot应用程序的工具。它提供了一组功能,可以帮助开发人员将旧版本的Spring Boot应用程序迁移到新版本,以便利用新的功能和修复的问题。

    功能特点

    • 依赖升级:Spring Boot Migrator可以自动分析应用程序的依赖关系,并提供建议的依赖升级路径。它可以检测到过时的依赖项,并提供更新的版本,以确保应用程序能够使用最新的功能和修复的问题。
    • 配置迁移:Spring Boot Migrator可以帮助开发人员将旧版本的配置文件迁移到新版本的Spring Boot应用程序。它可以自动识别配置文件中的变化,并提供相应的修改建议,以确保配置文件与新版本的应用程序兼容。
    • 代码重构:Spring Boot Migrator可以自动识别旧版本Spring Boot应用程序中的过时代码,并提供相应的重构建议。这有助于开发人员改进代码质量和可维护性,并使其适应新版本的Spring Boot。

    SBM的主要用途就是Spring Boot的迁移和升级。

  • Mermaid图表绘制工具

    Mermaid是一个开源的图表绘制工具,它使用简单的文本语法来描述图表,支持绘制流程图、时序图、甘特图等多种类型的图表。Mermaid的设计目标是提供一种简单、直观的方式来创建图表,使得非专业的用户也能轻松绘制出美观的图表。

    对比于Plantuml,Mermaid内置支持的图表类型更多,且相对美观度高一些。Mermaid还有一个便利就是它在GitHub 和 GitLab 等流行源代码存储库中得到原生支持,从而可以在 Markdown 文档中嵌入并轻松更新 Mermaid。

    使用示例

    下面是一个简单的Mermaid语法示例,用于绘制一个流程图:

    graph LR
        A[开始] --> B[中间步骤]
        B --> C[结束]

    通过上述代码,可以生成一个包含三个节点的流程图,节点之间的关系用箭头表示。

    这只是Mermaid语法的一个简单示例,实际上Mermaid支持更复杂的语法和功能,可以绘制出更丰富的图表。

    集成

    Mermaid可以方便集成在WordPress里面,下面是一些示例

    journey title My working day section Go to work Make tea: 5: Me Go upstairs: 3: Me Do
  • Torznab 协议

    在使用Sonarr等工具的时候,我们总会遇到找不到资源的情况,特别是一些冷门的中文资源(国产剧等)就更复杂了。

    Sonarr搜索资源用的比较多的是搭配Jackett走Torznab协议。Torznab 协议是一种用于搜索引擎的协议,它可以帮助搜索引擎更方便地搜索 BitTorrent 网络中的资源。

    Torznab 协议有以下特点:

    1. 标准化:Torznab 协议是一种标准化的协议,可以帮助搜索引擎更方便地搜索 BitTorrent 网络中的资源。
    2. 可扩展性:Torznab 协议支持多种参数,可以帮助搜索引擎更精确地搜索所需的内容。
    3. 易于实现:Torznab 协议的实现相对简单,开发者可以根据自己的需求选择适当的客户端库和示例代码,来实现搜索引擎的功能。
    4. 支持多种语言:Torznab 协议的客户端库支持多种编程语言,包括 C#、Java、Python、Ruby 等。
    5. 支持多种索引站点:Torznab 协议可以支持多种索引站点,包括私有站点和公共站点,可以帮助搜索引擎更全面地搜索 BitTorrent 网络中的资源。

    当一个资源无法是私有或者根本就不是标准BitTorrent网络资源时,我们可以自己实现一套,帮助Sonarr自动下载需要的资源。

    参数

    Torznab 协议支持多种参数,以下是常见的一些参数:

    • apikey:API 密钥,用于身份验证和授权。
    • q:搜索关键字,用于指定搜索的内容。
    • cat:资源分类,用于指定搜索的资源类型,如电影、电视剧、音乐等。
    • limit:搜索结果数量限制,用于指定搜索结果的数量。
    • offset:搜索结果偏移量,用于指定搜索结果的起始位置。
    • imdbid:IMDb 编号,用于指定搜索的电影或电视剧。
    • tvdbid:TVDB 编号,用于指定搜索的电视剧。
    • tvmazeid:TVMaze 编号,用于指定搜索的电视剧。
    • season:季数,用于指定搜索的电视剧季数。
  • 在Rust中使用mimalloc

    mimalloc是一个高效的内存分配器,它被设计用于在多核系统上提供高吞吐量和低延迟。它的特点是快速、节省内存、可扩展和线程安全。mimalloc还支持内存对齐和内存池等高级特性。

    要在Rust项目中使用mimalloc,需要使用mimalloc-sys crate。mimalloc-sys是一个Rust绑定,它提供了对mimalloc的C接口的访问。

    首先,在Cargo.toml文件中添加以下依赖项:

    [dependencies]
    mimalloc-sys = "0.1.18"

    然后,在Rust代码中,使用以下代码初始化mimalloc:

    extern crate mimalloc_sys;
    
    use std::alloc::{GlobalAlloc, Layout};
    use std::ptr::null_mut;
    
    struct Mimalloc;
    
    unsafe impl GlobalAlloc for Mimalloc {
        unsafe fn alloc(&self, layout: Layout) -*mut u8 {
            mimalloc_sys::mi_malloc(layout.size()) as *mut u8
        }
    
        unsafe 
  • Rust调用C++库

    Rust调用C++库

    Rust基于FFI可以调用其他语言,这个支持对于C是很完备的,对于C++有一些限制。常用的工具有cxx和autocxx,前者可控简单,后者强大易用。我一般喜欢使用autocxx,可以少写一些代码。

    我们这里用Rust调用V8为例子。

    打印固定字符串

    首先引入autocxx

    [dependencies]
    autocxx = "0.25.0"
    cxx = "1.0"
    
    [build-dependencies]
    autocxx-build = "0.25.0"

    我们先尝试查询一下V8的版本号。

    新建input文件,定义一个方法version,先返回一个固定字符串。

    inline std::string version() {
        return "0.0.1";
    }

    main.rs方法添加代码

    use autocxx::prelude::*;
    include_cpp! {
        #include "../include/input.h"
        safety!(unsafe_ffi)
        generate!("version")
    }
    
    fn main() {
        let rv8 = 
  • V8预构建

    V8 是 Google 为 Chrome 浏览器设计的 JavaScript 执行引擎,其初衷与目标是为 Chrome 设计一个领先行业的高性能 JavaScript 引擎。V8之后的流行和广泛应用已经超过了单纯为Chrome服务的目的的,大量应用也通过嵌入V8获得了JavaScript相关能力。

    V8的代码庞大,构建工具使用Ninja,由于外部依赖和网络问题,部分工具获取本来就比较困难,加上使用V8的场景一般需要交叉编译,比如在ubuntu上编译后给Android使用,编译费时费力。由于官方没有提供预构建包,这个工作必须要自己完成,网络上虽然有大量第三方个人构建的,但是由于配置复杂性和版本多样,很多并不符合需求。

    V8的版本选择我比较偏好跟随Node,比如Node当前版本使用的V8版本为10.8.168.25。

    首先是确定需求,比如我目前比较需要一个完整的静态包,那么需要的参数如下

    is_component_build = false
    use_custom_libcxx = false
    v8_enable_i18n_support = false
    v8_use_external_startup_data = false
    v8_symbol_level = 0
    v8_static_library = true
    v8_monolithic = true

    这样最终产物就是libv8_monolith.a。配置可以基于v8gen.py生成不同平台和系统的,然后再追加我们的参数,比如android armv8就可以使用

    python3 ./tools/dev/v8gen.py 
  • 华为运动健康转为TCX数据

    华为运动健康转为TCX数据

    华为运动健康是华为下面的健康APP,配合华为各种穿戴和健康类设备,可以获取丰富的运动健康数据。其中一部分设备价格低廉,数据获取性价比高,而且还可以结合部分手机传感器,提高精度的同时也降低了成本。华为APP自身虽然提供了一部分分析功能,但是相对简单,而且内部算法不透明,加上华为运动健康导出数据不带心率,这样数据根本没法直接使用。这种情况下就需要对数据进行二次处理和分析。我们用最廉价的方案 ,手环+GPS手机针对跑步、骑行数据举例。

    原始数据获取

    华为运动健康APP可以导出数据,但是数据只包含GPS坐标,没有心率、步频等数据,这样的数据实际上是没有价值的。这里有两个办法,一个是换区,由于国内外数据权利和安全等规定不同,海外区可以申请获取数据,虽然需要一定的手动操作,但是毕竟可以直接获取。第二个方法就是借助第三方APP,比如Health Sync导出数据。Health Sync提供一个月的试用,价格也不贵,相对来说是一个上手容易的选择,但是遗憾的是Health Sync导出的数据有一些问题,特别是在坐标偏移上,而且同步的数据也是经过加工的,本质上不是原始数据。

    Health Sync获取数据的原理是通过华为运动健康的API获取数据,然后转为第三方平台的格式。这里我们也可以使用同样的思路。

    通过参考华为官方的开发者文档,我们可以明确如下步骤:

    • 申请开发者账号
    • 申请健康数据权限
    • 使用自己的账号进行Oauth2登陆
    • 使用凭证访问数据

    申请步骤就不提了,大家可以按需操作。Oauth2的认证方式有4种,既然考虑到单纯获取数据,直接走无服务化的模式,access token有效期1小时,每次使用都需要登陆。

    由于官方SDK只有Android和JS的包,只能使用Rest API。这个API设计要按照文档来,详情数据是通过列表获取的,原始数据的数据类型如下:

    • com.huawei.instantaneous.exercise_heart_rate
    • com.huawei.instantaneous.location.sample
    • com.huawei.instantaneous.steps.rate
    • com.huawei.instantaneous.speed

    分别对应心率、位置、步频、速度,由于设备本身的限制,心率和GPS相对可用,步频采样频率低,可供参考,华为还有一个sTag,精英版是2个,佩戴在足部,这个可以提供将近10种跑步数据,这个设备提供的步频、步幅有价值。

    原始数据格式基本都是根据dataTypeName判断数据类型,再根据数据类型,从values里面针对获取。下面是一段示例

    {
      "startTime": 1673587058212000000,
      "endTime": 1673587679688000000,
      "dataCollectorId": "raw:com.huawei.instantaneous.exercise_heart_rate:com.huawei.health:HUAWEI Health:HUAWEI Health:1190533025:1190533025",
      "samplePoints": [
        {
          "startTime": 1673587060000000000,
          "endTime": 1673587060000000000,
          
  • 使用UpdraftPlus备份博客数据到阿里云OSS

    WordPress的UpdraftPlus插件进行博客数据备份,包括数据库数据、各类文件等,还支持灵活的备份周期和保留策略。

    默认情况备份都是备份到当前服务器的,如果出现了一些问题或者需要迁移,显然这样不太满足需求。最好讲数据进行远程备份。

    UpdraftPlus有付费版本,付费版本支持更多类型的远程存储,但是免费版本就提供了S3的支持,可以支持很多云服务厂商。阿里云的OSS价格便宜,买年包几元钱可以买一年40G的存储。如果你的博客服务器也是阿里云的,还可以走内网存储。

    配置示例如图

    S3位置就是的oss bucket name,节点可以根据你的情况选择,主要看地域和是否内网。访问密钥就是账号的key对,可以创建一个专用子账号,如果图简单,也可以用主账号的。…

  • 在铁威马Nas上运行Rust多语言混合项目

    在铁威马Nas上运行Rust多语言混合项目

    手上有一台铁威马Nas,4盘位双核CPU,X86架构的机器。铁威马的硬件还可以,性价比比较足,但是生态很一般,对于相册的管理方面,官方的不怎么满意,在外网找了几个要么功能太简陋,要么内存占用太高,带不动。

    搞来搞去还是自己弄一个,考虑到性能和开销问题,最后选择的是Rust语言,想着横竖都能编译到机器上运行,实在不行Nas还支持Docker,也能解决一部分问题。由于照片太多,所以使用了Tensorflow框架配合MobileNetV2模型进行照片分类和人脸识别,模型都是S规模的,开销可控。

    在开发机器上开发好以后直接打包成Docker准备试试,由于使用了Vue作为前端,所以打包分两部分,先构建前端,然后构建后端,最后产出最终镜像。Dockerfile文件如下:

    FROM node:16 as front
    WORKDIR /usr/src/pototd
    COPY ./webapp ./webapp
    RUN cd webapp && npm install && npm run build
    
    FROM rust:1.62.1 as builder
    COPY --from=front /usr/src/pototd/webapp/dist /usr/src/pototd/webapp/dist
    
    RUN apt update && apt install -y libssl-dev musl-tools libsqlite3-dev