Jiahong 的个人博客

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

ML——各种数据分析图介绍.md

[日常编辑]
Python数据分析时可能用到各种各样的图,本文将简单介绍数据分析中常用的几种基本图


直方图(Hist-plot)


柱形图(Dist-plot)

seaborn.distplot

  • 集合了matplotlib的hist()与核函数估计kdeplot的功能

核密度估计图(KDE-plot)

seaborn.kdeplot


箱式图(Box-plot)

  • 箱式图,是指—种描述数据分布的统计图
  • 是表述最小值、第一四分位数、中位数、第三四分位数与最大值的一种图形方法
  • 可以粗略地看出数据是否具有对称性,分布的分散程度等信息

异常值

又称离群值(Outlier), 指不在区间[Q1-1.5IQR, Q3+1.5IQR]中的值

  • Q1为25%中位数,也称为下四分位数
  • Q3为75%中位数,也称为上四分位数
  • IQR为Q3-Q1,四分数间距

绘图方法

去除离群值之后的部分计入图中,分别标记五个特征值

  • 特征值 最小值,Q1,中位数,Q3,最大值
  • 将五个数值描绘在一个图上,五个特征值在一个直线上
  • 最小值和Q1连接起来,Q1、中位数、Q3分别作平行等长线段
  • 连接两个四分位数构成箱子
  • 连接两个极值点与箱子,形成箱式图
  • 最后点上离群值

实例

  • 箱式图示例:

小提琴图(Violin-plot)

  • 用于显示数据分布及其概率密度
  • 竖向显示类似于箱式图,横向表征密度分布,越宽的地方密度分布越高

ML——机器学习中的编码方式

One-hot encoding与Dummy-encoding易混淆点区分
Label Encoding标签编码


独热码(One-Hot code)

  • 又称独热编码、一位有效编码,直观来说就是有多少个状态就有多少比特,而且只有一个比特为1,其他全为0的一种码制
  • 其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效

 哑变量编码(Dummy encoding)

  • 哑变量编码直观的解释就是在One-Hot编码的基础上任意的将一个状态位去除
    • 比热独码少一维即可编码
  • 可以理解为多个状态位之间是相关的,已知n-1个那么可以推出剩下的那个
    • 比如已知前n-1个状态位为0,那么最后一位一定为1
    • 一种做法是: 全0算是一维(理解: 由于全0可以默认最后一位为1, 其他非全0的可以默认最后一维为0,所以能够区分不同样本)

哑变量(Dummy variable)

亦称指示变量(Indicator variable)

  • 以上两种编码得到的变量都称为指示变量或者哑变量

为什么需要One-Hot编码?

  • 大部分算法是基于向量空间中的度量来进行计算的,为了使非偏序关系的变量取值不具有偏序性,并且到圆点是等距的, 使用one-hot编码, 将离散特征的取值扩展到了欧式空间, 离散特征的某个取值就对应欧式空间的某个点, 将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理
  • 将离散特征通过one-hot编码映射到欧式空间,是因为,在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间

独热编码优缺点

优点

  • 独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用
  • 它的值只有0和1,不同的类型存储在垂直的空间
  • 数据天然归一化了, 非常优秀

缺点

  • 当类别的数量很多时,特征空间会变得非常大
    • 一般可以用PCA来减少维度
    • One-Hot encoding + PCA 这种组合在实际中也非常有用

什么时候不用独热编码

  • 有些基于树的算法在处理变量时,并不是基于向量空间度量,数值只是个类别符号,即没有偏序关系,所以不用进行独热编码, 典型的代表如XGBoost, LightGBM等
  • 存在偏序关系的特征,不能用独热编码, 独热编码会使得特征失去原来的偏序关系

标签编码

Label Encoding

  • 将类别编码为连续的数值类型(0,1,2,3…)
  • 举例
    1
    2
    3
    4
    5
    6
    7
    from sklearn.preprocessing import LabelEncoder
    le = LabelEncoder()
    le.fit([1,8,9,67,5,8,6])
    print(le.transform([1,1,8,9,67,5,5]))

    # Output:
    [0 0 3 4 5 1 1]

附录: 机器学习过程

ML——课程学习


整体说明

  • 在机器学习领域,课程学习(Curriculum Learning,CL) 训练策略,适用场景广泛,包括监督学习,强化学习等场景
  • 课程学习的核心思想是让模型从简单任务逐步过渡到复杂任务,如同人类在学习新知识时先掌握基础概念,再逐渐挑战更难的内容
  • 思路 :人类学习遵循“从易到难”的顺序,课程学习希望通过模拟这一过程,提升机器学习模型的学习效率和泛化能力
  • 定义 :通过设计一个“课程”,即按照任务难度排序的训练数据序列,让模型先在简单任务上学习,再逐步增加任务复杂度,最终掌握目标任务
  • 优点:
    • 从简单任务入手可帮助模型更快收敛,减少训练时间(如CV中先学识别简单物体边缘,再学完整物体)
    • 逐步积累的知识体系让模型更适应复杂场景,减少过拟合(如语音识别中先学干净语音,再学带噪声语音)
    • 复杂任务直接训练可能陷入局部最优,课程学习通过分阶段优化降低难度(如神经网络训练中的逐层预训练)
  • 它不仅适用于传统监督学习,还在强化学习、多任务学习等领域展现出潜力。随着算法对“任务难度”理解的深化,未来课程学习可能成为解决复杂AI任务的关键策略之一

课程学习中的核心概念

  • 任务难度定义 :衡量任务的“难易程度”,常通过数据的特征复杂度、样本数量和模型在任务上的预测准确率等来评估任务难度
  • 课程设计策略 :人工划分或自动划分
    • NLP 中先学短文本分类,再学长文本(人工划分)
    • 基于数据相似度聚类,先训练简单簇,再逐步引入复杂簇(自动划分)
    • 根据模型当前表现,动态选择下一个合适的任务(自动划分)
  • 训练过程 :模型在每阶段完成后,保留已学知识,并将新知识与旧知识结合,避免“灾难性遗忘”

典型示例

  • CV-图像分类:先学识别猫狗等简单动物,再学区分稀有物种
  • CV-目标检测:先学大尺寸物体检测,再学小尺寸物体检测
  • NLP-机器翻译:先学短句翻译,再学复杂长句翻译
  • NLP-问答系统:先回答事实性问题,再处理推理类问题
  • RL-游戏AI:如 AlphaGo 先学基础落子规则,再学复杂策略
  • RL-机器人控制:先学基础动作(如行走),再学复杂任务(如避障)
  • 推荐系统:先学基础用户偏好,再学个性化长尾推荐

一些相关名词辨析

  • 课程学习
    • 主动按难度排序任务,强调“从易到难”的顺序性,适用于复杂任务分步训练
  • 迁移学习
    • 从源任务迁移知识到目标任务,重点在知识迁移而非任务排序,主要强调跨领域知识复用
  • 元学习
    • 强调学习“如何学习”,关注快速适应新任务的能力,着重在少样本学习场景中使用
  • 增量学习
    • 逐步添加新数据,防止遗忘旧知识,重点在记忆保留,主要在动态数据场景

ML——误差棒简单介绍

Reference[1]: 维基百科
Reference[2]: How to Calculate Error Bars?


误差棒

(Error bar, 也称为误差线)

显示潜在的误差或相对于系列中每个数据标志的不确定程度

  • 误差线可以用标准差(standard deviation)或者标准误差(standard error),一般用标准差

标准差与标准误差

  • 标准差是离均差平方和平均后的方根
  • 标准误是标准误差,定义为各测量值误差的平方和的平均值的平方根
  • 标准差与均数结合估计参考值范围,计算变异系数,计算标准误等。标准误用于估计参数的可信区间,进行假设检验等
  • 当样本含量 n 足够大时,标准差趋向稳定;而标准误随n的增大而减小,甚至趋于0

计算误差棒

  • Step1: 计算均值 E
  • Step2: 计算标准差 D
  • Step3: 计算误差棒的两端值
    • barBegin = E-D
    • barEnd = E+D

Git——Submodule管理


整体说明

  • submodule 允许 git 灵活地将其他项目嵌入到当前项目,同时自由地切换 sumodule 分支和内容管理,且保持各自的版本独立
  • 本质上: submodule 还是作为一个独立的项目存在的,主项目管理子模块靠 .gitmodules 文件
  • 子模块默认跟踪的是固定 commit ID ,而非分支:
    • 若子仓库更新,主仓库需手动更新子模块的 commit ID 并提交;
  • .gitmodules 是子项目的核心文件
    • 这个文件必须纳入版本控制,否则他人克隆仓库时无法识别子模块;
  • 避免嵌套过深的子模块,否则会增加版本管理和协作的复杂度

添加子模块

  • 基础语法

    1
    2
    3
    git submodule add <子仓库URL> <本地存放路径(可选)>
    # 上述命令会自动添加 submodule 相关的必要文件,立刻直接 commit 即可添加 submodule 完成,注意这里如果先执行 checkout 等可能导致 submodule 信息无法对齐,建议立即 commit
    git commit "Add: submodule xxx"
    • <子仓库URL>:子模块的 Git 仓库地址(HTTPS/SSH 均可)
    • <本地存放路径>:子模块在当前仓库中的存放目录(省略则默认用仓库名)
  • 若需让子模块跟踪分支,可添加 -b <分支名> 参数:

    1
    git submodule add -b <branch> <子仓库URL> <路径>
  • submodule 的分支可以切换绑定(或新增绑定)

    1
    2
    3
    4
    git config -f .gitmodules submodule.<本地存放路径>.branch <branch>

    # 比如将 dev 分支绑定到名为 libs/sub-repo 的 submodule 下:
    git config -f .gitmodules submodule.libs/sub-repo.branch dev

示例

  • 示例:比如将 https://github.com/example/sub-repo.git 添加到当前仓库的 libs/sub-repo 目录:

    1
    2
    3
    4
    # 进入主仓库根目录
    cd /path/to/your/main-repo
    # 添加子模块
    git submodule add https://github.com/example/sub-repo.git libs/sub-repo
  • 执行上述命令后,Git 会自动完成以下操作:

    • 1)在指定路径(如 libs/sub-repo)拉取子仓库的代码;

      • 就像是普通的 git 项目一样,还包括 .git 目录
    • 2)在主仓库根目录生成 .gitmodules 文件(记录子模块配置),内容示例:

      1
      2
      3
      [submodule "libs/sub-repo"]
      path = libs/sub-repo
      url = https://github.com/example/sub-repo.git
    • 3)主仓库的暂存区会新增 .gitmodules 和 libs/sub-repo 两个条目(子模块条目是一个“链接”,记录子仓库的 commit ID)

添加后续提交子模块到主仓库

  • 添加子模块后,需要将 .gitmodules 和子模块条目提交到主仓库:
    1
    2
    3
    4
    # 提交变更
    git commit -m "添加子模块 sub-repo 到 libs 目录"
    # 推送到远程
    git push

克隆包含子模块的仓库

  • 直接 git clone 只会拉取子模块目录,但不会拉取子模块的代码,需执行:
    1
    2
    3
    4
    5
    6
    7
    8
    # 方式1:克隆时直接拉取子模块
    git clone --recurse-submodules <主仓库URL>

    # 方式2:先克隆主仓库,再初始化+更新子模块
    git clone <主仓库URL>
    cd main-repo
    git submodule init # 初始化子模块配置(读取.gitmodules)
    git submodule update # 拉取子模块的代码

git submodule update vs git submodule update --remote

  • git submodule update 命令还有个特殊参数 --remote,两者有很多容易犯错的区别
  • git submodule update
    • 用于 对齐主项目固定的子模块版本
    • 仅将子模块切换到主项目记录的哈希值(即 .gitmodules/.gitmodules 中固定的子模块版本);
    • 不会主动从子模块的远程仓库拉取新代码;
    • 若子模块本地无该哈希值的代码,会从远程克隆,但仅克隆该版本
    • 同步主项目指定的子模块版本(比如团队协作时,确保所有人用相同版本的子模块)
    • 执行 git submodule update 后:
      • 子模块处于「分离头指针(detached HEAD)」状态,且版本与主项目记录完全一致;
  • git submodule update --remote
    • 用于 更新子模块到远程最新版本
    • 先从子模块的远程仓库拉取最新代码(更新子模块的远程追踪分支);
    • 再将子模块切换到该远程分支的最新哈希值;
    • 会修改主项目中记录的子模块版本(需手动提交主项目的修改)
    • 主动更新子模块到远程最新版本(比如子模块有新功能/修复,需要同步到主项目)
    • 执行 git submodule update --remote 后:
      • 子模块仍处于「分离头指针」状态(仅指向远程最新哈希),主项目的 git 状态会显示子模块版本已修改
      • 需执行 git add <子模块路径> && git commit 才能将新的子模块版本记录到主项目
    • 慎用这个命令

git submodule update vs git submodule update --remote 示例

  • 假设主项目 main-proj 包含子模块 sub-proj:

  • 同步主项目指定的子模块版本:

    1
    git submodule update
  • 更新子模块到远程最新版本,并提交主项目的版本修改:

    1
    2
    3
    4
    git submodule update --remote sub-proj  # 拉取sub-proj远程最新代码,切到最新哈希
    # 提交主项目的修改
    git add sub-proj
    git commit -m "update sub-proj to latest remote version"

附录:初始化带有 submodule 的仓库详细理解

  • 正常拉取外层项目

    1
    git pull origin master:master
    • 此时除了 ./.gitmodules 文件包含关于子模块的信息外,其他的文件都不包含,包括 ./.git/ 中
  • 初始化子模块

    1
    git submodule init
    • 将 .gitmodules 中的所有子模块注册到外层项目中
    • 注册方式:添加子模块信息(文件夹路径和子模块项目地址)到 .git/config 文件中并指明子模块对应的 active = true
    • 注:如果子模块之前存在于 .git/config 中 且 active = false,这个初始化操作会修改为 active = true
  • 初始化指定子模块(其他子模块可以不初始化,也不会影响,未初始化的子模块会是一个空文件夹)

    1
    git submodule init <path_to_sub_module_name>
    • 仅初始化 <path_to_sub_module_name> 这个模块
      • 测试发现:注意初始化时 <path_to_sub_module_name> 是 submodule 的文件夹路径
      • 可以是相对路径或绝对路径,执行这个命令时需要在 submodule 的外面
  • 更新子模块

    1
    2
    3
    4
    # 更新所有子模块('.git/config' 和 '.gitmodules' 中的所有子模块)
    git submodule update
    # 更新单个路径下对应的模块
    git submodule update <path_to_sub_module_name>
    • 具体含义:根据主仓库中记录的 子模块 commit ID ,从子模块的远程仓库拉取对应版本的代码,并存放到主仓库指定的子模块路径中
    • 这行代码执行下面的操作:
      • 如果还没有下载,则所有子模块的链接地址项目下载到 .git/modules/ 中
      • 将对应的 commit ID checkout 到 submodule 文件夹(工作目录)中
      • 常常用来在切换分支后同步子模块数据
    • <path_to_sub_module_name> 模块参数的使用方法同上
  • 特别注意:

    • git submodule init 后,.git/config 和 .gitmodules 应该是一致的
    • .git/config 和 .gitmodules 中都有,且在 .git/config 中 active = true 的 submodule 才能被 update 操作下载和 checkout
  • 特别说明:解耦初始化 deinit

    1
    2
    3
    4
    5
    # 将 <path_to_sub_module_name> 初始化,后续执行 git submodule update 等命令时自动更新 <path_to_sub_module_name> 这个 submodule 
    git submodule init <path_to_sub_module_name>

    # 将 <path_to_sub_module_name> 解耦初始化,后续执行 git submodule update 等命令时不会再自动更新 <path_to_sub_module_name> 这个 submodule
    git submodule deinit <path_to_sub_module_name>

更新子模块到自己的最新 commit

  • 更新逻辑:
    1
    2
    3
    4
    5
    6
    7
    # 进入子模块目录
    cd libs/sub-repo
    git pull origin master # 拉取子仓库最新代码
    cd ../.. # 回到主仓库
    git add libs/sub-repo # 提交子模块的新 commit ID
    git commit -m "update: 子模块 sub-repo 同步到最新版本"
    git push

删除子模块

  • 若需移除子模块,步骤稍多(Git 无直接 git submodule delete 命令):
    1
    2
    3
    4
    5
    6
    7
    8
    # 1. 解除子模块关联
    git submodule deinit -f libs/sub-repo
    # 2. 删除 .git 中的子模块缓存
    rm -rf .git/modules/libs/sub-repo
    # 3. 删除工作区的子模块目录,这一步后会看到 .gitmodules 中的相关 submodule 也被删除了
    git rm -f libs/sub-repo
    # 4. 提交删除操作
    git commit -m "remove: 移除子模块 sub-repo"

附录:关于 Git submodule 的理解

  • submodule 自己知道自己被当做 submodule

    • 一个项目被作为 submodule 后,他的 ./submodule_name/.git 将不再是一个文件夹,而是一个指明 .git/ 文件夹路径的配置文件

      1
      cat ./submodule_name/.git

      gitdir: ../.git/modules/submodule_name

    • .git/文件夹可以在./.git/modules/submodule_name/.git/中找到

  • submodule 相关信息都在外层项目中显示出来

  • 在 submodule 文件夹./submodule_name/下, submodule 的更新,提交等操作正常按照一般项目进行即可

    • 这里操作时虽然仓库在外层项目的./.git/modules/submodule_name/.git/中,但是在 submodule 的目录下我们可以正常访问 submodule 的仓库
    • 也就是说在 submodule 文件夹下的git操作(add, commit)实际上不修改当前文件夹下的任何文件,修改都在外层项目的./.git/modules/submodule_name/.git/仓库中
  • 外层项目只存储

    • submodule 文件夹
    • 在./.gitmodules中存储 submodule 相关信息(文件夹路径与 submodule 远程地址)
    • 在GitHub中,直接用网页打开项目可以看到 submodule 会被自动解析远程地址和最近提交的ID信息,点击 submodule 对应的文件夹链接即可跳转到 submodule 远程仓库地址中

递归 submodule

  • 递归时记住项目的库都在父项目的库中即可
    • 这句话等价于所有项目的库都在根项目的 .git/ 中

特别说明

  • 非必要不建议使用 submodule

附录:移除 submodule .git 但内容保留到主项目

  • 如果 Git 项目下面有个 submodule 也是包含 Git 的(可能是 git clone 命令下载的)的,往往不能正常的提交和管理项目,这是因为项目变成了 Git submodule 了
  • 现象:如果 submodule 是 git clone 别人的项目,我们将 submodule 提交到整个大项目中时
    • 会提示:modified:xxx(modified content, untracked content)
    • 此时如果直接提交,那么远程仓库里面 submodule 将是空的
  • 若不想再保留 submodule 的 git 仓库,则需要删除 submodule 相关的所有信息

第一步:需要先删除子模块

  • 移除子模块:
    1
    2
    3
    4
    # 1. 解除子模块关联
    git submodule deinit -f libs/sub-repo
    # 2. 删除 .git 中的子模块缓存
    rm -rf .git/modules/libs/sub-repo

第二步:重新添加文件路径(当做普通的文件)

  • 重新添加 submodule 文件夹
    1
    git add xxx

git submodule 是否跟踪分支的区别

  • 在 Git 中使用子模块(Submodule)时,“不跟踪分支(默认行为/锁定特定提交)” 和 “跟踪分支” 的核心区别在于父项目(Superproject)如何决定子模块应该停留在哪个版本 ,以及 更新子模块时的流程

不跟踪分支(默认行为 / 锁定特定 Commit)

  • 这是 Git 子模块最原始也是最常用的工作方式
  • 父项目只关心:“子模块必须是 a1b2c3d 这个提交”,不在乎这个提交属于哪个分支,也不在乎这个提交是不是最新的
  • 当克隆父项目并运行 git submodule update 时,Git 会进入子模块目录,强制将其 checkout 到父项目记录的那个 SHA-1 哈希值
    • 注:此时,子模块处于 Detached HEAD(游离指针)状态
  • 不跟踪分支时,如果要切换到某个分支的最新 commit,需要执行如下操作:
    • 1)进入子模块目录:cd submodule_dir
    • 2)手动拉取或切换:git checkout master && git pull
    • 3)回到父项目目录:cd ..
    • 4)提交变更:git add submodule_dir -> git commit
  • 建议使用这种方式, 团队所有成员拉取代码后,得到的子模块代码完全一致,不会因为子模块远程仓库更新了代码而导致父项目构建失败

跟踪分支

  • 可通过配置 .gitmodules 文件来实现的一种更动态的模式

  • 在 .gitmodules 中明确告诉 Git:“这个子模块应该跟随 main (或 dev) 分支”

    • 也可以通过命令行绑定,如添加 submodule 时,或之后直接修改:

      1
      2
      3
      4
      5
      6
      7
      8
      # # 新建 submodule:
      git submodule add -b submodule_master https://github.com/xxx/lib.git
      # 此时 .gitmodules 中会添加 branch = submodule_master

      # # 已有 submodule 绑定某个 分支:
      git config -f .gitmodules submodule.<本地存放路径>.branch <branch>
      # 比如将 dev 分支绑定到名为 libs/sub-repo 的 submodule 下:
      git config -f .gitmodules submodule.libs/sub-repo.branch dev
    • .gitmodules 文件中会多一行配置:

      1
      2
      3
      4
      [submodule "my-lib"]
      path = my-lib
      url = https://github.com/example/my-lib.git
      branch = main # 多出来的配置
  • 虽然父项目在数据库中依然存储的是 SHA-1 哈希值,但当你使用特定参数更新时(update 时添加 --remote),Git 会忽略本地记录的哈希值,直接去拉取远程分支的最新代码

  • 跟踪分支时,如果要切换到某个分支的最新 commit,只需要执行如下操作:

    • 不需要进入子模块目录,只需在父项目根目录运行:

      1
      git submodule update --remote
      • Git 会自动去子模块的远程仓库抓取 branch 字段指定分支的最新提交,并将子模块更新到该提交
      • 注意:如果不添加 --remote 则只是切换到当前 commit_id 而不会拉取最新分支(这与不绑定分支的 git submodule update 执行含义完全相同)
    • 注:运行完上述命令后,父项目的状态会显示子模块有变化(指向了新的 Hash),仍然需要 在父项目中执行 git add 和 git commit 来固化这个变更

  • 如果开发的项目依赖另一个正在快速迭代的库,且总是希望使用该库的最新版本,这种方式可以简化更新流程,但是要小心使用

一些实操及理解

  • 新增 submodule 时,默认(不跟踪):

    1
    2
    git submodule add https://github.com/xxx/lib.git
    # 此时 .gitmodules 中没有 branch 字段
  • 新增 submodule 时,跟踪分支:

    1
    2
    git submodule add -b main https://github.com/xxx/lib.git
    # 此时 .gitmodules 中会添加 branch = main
  • 更新 submodule 默认(不跟踪):

    • 如果运行 git submodule update,什么都不会发生 ,因为它只会把子模块恢复到父项目当前记录的旧 Hash 值
  • 更新 submodule (若 .gitmodules 中已经跟踪分支):

    • 如果运行 git submodule update,什么都不会发生 ,因为它只会把子模块恢复到父项目当前记录的旧 Hash 值,与 .gitmodules 中是否已经跟踪分支无关
    • 如果运行 git submodule update --remote,Git 会检测到配置了分支,于是去拉取远程最新代码,并更新本地子模块的指针
  • 特别说明:

    • “跟踪分支” 不意味着自动更新:即使配置了跟踪分支,当 git pull 父项目时,子模块不会自动更新到远程最新
      • 必须显式执行 git submodule update --remote
    • “跟踪分支” 后父项目仍然会记录 Hash 值,Git 的底层数据结构决定了父项目永远 只记录子模块的 Commit Hash
      • 所谓“跟踪分支”,只是提供了一个快捷命令(--remote)来帮你自动找到那个最新的 Hash 值并 checkout 过去,省去了手动进入子目录 pull 的过程
    • 如果是引用第三方稳定的开源库 ,或者要求构建环境绝对可复现,使用默认(不跟踪) 模式
    • 如果是迭代很快的开发,且父项目需要时刻集成子模块的最新开发成果,使用跟踪分支 模式

Ubuntu——安装Ubuntu后要首先要做的事情

原生的Ubuntu有许多没用的软件和包,也有很多我们需要但是没装的软件和包,论文将介绍安装Ubuntu后一般来说需要对系统做哪些自定义的修改,可按照需要选择适合的软件


删除几乎不用的软件

  • 以下软件均可删除

    1
    2
    3
    4
    sudo apt-get remove libreoffice-common
    sudo apt-get remove unity-webapps-common
    sudo apt-get remove thunderbird totem rhythmbox empathy brasero simple-scan gnome-mahjongg aisleriot gnome-mines cheese transmission-common gnome-orca webbrowser-app gnome-sudoku landscape-client-ui-install
    sudo apt-get remove onboard deja-dup
  • 删除的软件参考自其他博客:安装Ubuntu 21.04后要做的事


安装Vim

  • 命令:
    1
    sudo apt-get install vim

安装 Google Chrome

  • 命令:
    1
    2
    3
    4
    5
    6
    7
    8
    cd ~/Downloads
    wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
    sudo apt-get install libappindicator1 libindicator7
    sudo dpkg -i google-chrome-stable_current_amd64.deb
    sudo apt-get -f install

    # 运行chrome
    google-chrome

安装 Oracle Java

  • 命令:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sudo add-apt-repository ppa:webupd8team/java  
    sudo apt-get update
    sudo apt-get install oracle-java8-installer

    # 删除残留
    sudo rm /usr/share/upstart/sessions/jayatana.conf

    # 测试安装成果
    java -version
    # 如果第一行是版本号则成功

安装经典菜单指示器

  • ClassicMenu Indicator, 用于代替Ubuntu自带的应用检索器
    1
    2
    3
    sudo add-apt-repository ppa:diesch/testing
    sudo apt-get update
    sudo apt-get install classicmenu-indicator

安装系统指示器 SysPeek

  • 查看系统管理,包括内存和CPU消耗等
    1
    2
    3
    sudo add-apt-repository ppa:nilarimogard/webupd8  
    sudo apt-get update
    sudo apt-get install syspeek

安装 Git

  • 命令:
    1
    sudo apt-get install git

安装 unrar

  • 命令:
    1
    2
    3
    4
    sudo apt-get install unrar

    # 使用命令
    unrar x test.rar

安装 flux 的 gui 版本 fluxgui

  • 脚本:
    1
    2
    3
    sudo add-apt-repository ppa:nathan-renniewaldock/flux
    sudo apt-get update
    sudo apt-get install fluxgui

安装网易云音乐

Note: 新版本1.1.0有问题,所以选择1.0.0版本
网易云1.0.0版本下载地址


安装Remmina

  • 一款开源的优雅的远程桌面GUI客户端
    1
    2
    3
    sudo apt-add-repository ppa:remmina-ppa-team/remmina-next
    sudo apt-get update
    sudo apt-get install remmina remmina-plugin-rdp libfreerdp-plugins-standard

如有问题参考Remmina安装链接


安装词典 GoldenDict

  • 一款崇尚自定义的词典

安装

  • 命令:
    1
    2
    3
    4
    # 安装词典
    sudo apt-get install goldendict
    # 安装En-En在线词库【可选】
    sudo apt-get install goldendict-wordnet

配置

  • 配置在线有道词典
    • Edit->Dictionaries->Websites->Add
    • Name: Youdao
    • Address: http://dict.youdao.com/search?q=%GDWORD%&ue=utf8
    • Enabled: Checked
    • ->Apply->OK
  • 配置 Bing 在线词典
    • 参考在线有道词典的配置
    • Name: Bing
    • Address: https://cn.bing.com/dict/search?q=%GDWORD%
  • 配置离线词典
    • 下载需要的词典: http://download.huzheng.org/zh_CN/
    • 解压
    • 将解压后的文件目录添加到字典中:
      • Edit->Dictionaries->Files->Add
      • 选中刚才的文件目录
      • ->Apply->OK
  • 开启划词翻译
    • 在 GoldenDict 主页点击小笔即可

安装 Shadowsocks

安装 Shadowsocksy 有两种方式,分别为命令行和Gui版本, 两种方式安装后都需要设置浏览器才能使用VPN

命令行版本安装

  • 安装命令:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 安装
    sudo apt-get update
    sudo apt-get install python-pip
    # 下面这行有时候可选
    sudo apt-get install python-setuptools m2crypto
    pip install shadowsocks
    sudo gedit /etc/shadowsocks.json

    # 配置文件
    {
    "server":"xx.xx.xx.xx",
    "server_port":xxxx,
    "local_address": "127.0.0.1",
    "local_port":1080,
    "password":"xxxxxxxx",
    "timeout":600,
    "method":"xxx",
    "fast_open": true,
    "workers": 1
    }

    # 运行
    sslocal -c /etc/shadowsocks.json

Shadowsocks Gui 版本安装

  • 从网站下载 release 版本: shadowsocks-qt5 GitHub

  • 添加运行权限:

    1
    chmod +x xxx
  • 现在双击即可运行

  • 在打开的 Gui 中导入 json 即可

  • 如果想把 Shadowsocks 添加到启动器,参考Utuntu——添加自定义的软件到启动器

浏览器配置

  • 以上两种版本安装配置后,想要用浏览器科学上网还需要配置浏览器
Firefox
>Menu
-> Preferences
-> Network Proxy Setting
-> Manual proxy configuration
-> Socks Host: 127.0.0.1:1080
-> SOCKS v5
Chrome
  • 分两种方式,一种是不用安装任何插件,在命令行启动时制定代理即可,一种需要安装SwitchyOmega插件

  • 直接使用命令行

    1
    2
    # 不用安装任何代理
    google-chrome --proxy-server=socks5://127.0.0.1:1080
  • 安装代理: Switchy Omega

  • 安装SwitchyOmega插件时需要科学上网,所以可以先用上面的命令行启动,然后使用Chrome安装SwitchyOmega插件*

  • 配置方面参考SwitchyOmega官网(自动切换模式配置方便): SwitchyOmega官网/Settings*


安装wps和字体

  • 安装libpng

    • 网站里面有多个源,可随意选一个下载
    • 也可使用命令直接下载
      1
      wget http://ftp.cn.debian.org/debian/pool/main/libp/libpng/libpng12-0_1.2.49-1+deb7u2_amd64.deb
  • 安装wps-office

  • 安装字体wps-office-fonts_1.0_all.deb


为Ubuntu添加Windows的字体

这个字体可以保证终端等能使用中文,同时能保证wps能正常使用

  • 从 Windows 系统的 Windows/Fonts/ 拷贝所有文件,大小大概500M+
  • 在 Ubuntu 上新建文件夹,建议放到 /usr/share/fonts/ 下面, 比如 /usr/share/fonts/win-fonts/
  • 将字体文件拷贝到新建立的文件夹下面
  • 执行下面命令
    1
    2
    3
    4
    cd /usr/share/fonts/
    sudo mkfontdir
    sudo mkfontscale
    sudo fc-cache

设置截图快捷键

在Windows和Mac下使用QQ快捷键截图习惯了后,到了Ubuntu会不习惯, 因为Ubuntu默认截图是保存到Pictures文件夹的,不是粘贴板
这里给出一种利用Ubuntu自带的软件gnome-screenshot实现QQ快捷键相同功能的方法

  • 添加快捷键Ctrl+Alt+A绑定到命令gnome-screenshot -ac
  • gnome-screenshot -c是全屏截图,也可以设置成自己喜欢的快捷键
  • gnome-screenshot参数简介
    • -c, 保存到剪贴板
    • -w, 截取当前窗口
    • -a, 选择一个区域
    • 如果没有任何参数默认是将当前全屏截图,并保存到Pictures文件夹
    • 更多gnome-screenshot参数参考gnome-screenshot -h

安装 sublime

  • 添加安装源

    1
    2
    3
    wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -
    sudo apt-get install apt-transport-https
    echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list
  • 更新库

    1
    sudo apt-get update
  • 用apt-get命令安装sublime

    1
    sudo apt-get install sublime-text
  • Sublime中输入中文

    1
    2
    3
    4
    5
    git clone --depth=1 https://github.com/lyfeyaj/sublime-text-imfix.git
    cd sublime-text-imfix
    ./sublime-imfix
    cd ..
    rm -rf sublime-text-imfix
    • 说明: 如果不执行这一步,Sublime 在 Ubuntu 中是不能直接输入中文的
  • 添加一点说明

    • 如果上面的方法不能安装最新版或者安装失败,可以尝试自己下载软件发行版并自己添加 sublime 到启动器,添加自定义程序到启动器的方法可参考 Utuntu——添加自定义的软件到启动器

关闭 sublime 的自动更新

  • Settings 中添加 "update_check": false,

Ubuntu——远程登录Ubuntu后只有一个$符号

对新添加的用户,我们远程登录Ubuntu后有时候只有一个$符号


问题描述

  • 对新添加的用户,远程登录Ubuntu后有时候只有一个$符号

问题原因

  • Ubuntu为新用户默认启动的是sh而不是bash
  • sh的命令比较少,只有一些ls, pwd这样的命令

解决方案

不修改源文件

  • 每次登录时先使用bash命令运行bash程序
  • 之后的指令都会是bash解释执行
  • 在bash中使用sh可会退到sh命令行
  • 该方法的缺陷在于多次执行bash和sh后,会造成进程嵌套多次,这样exit指令退出时需要多次

修改源文件

  • 标记文件/etc/passwd

    1
    sudo vi /etc/passwd
  • 找到用户对应的启动命令并将sh(可能没有sh,直接是空白)修改为bash

    1
    2
    3
    4
    # 修改前
    jiahong:x:1001:1001::/home/jiahong:
    # 修改后
    jiahong:x:1001:1001::/home/jiahong:/bin/bash

ML——xgboost包使用笔记

xgboost包中包含了XGBoost分类器,回归器等, 本文详细介绍XGBClassifier类


安装和导入

  • 安装

    1
    pip install xgboost
  • 导入

    1
    import xgboost as xgb
  • 使用

    1
    clf = xgb.XGBClassifier()

模型参数

普通参数

以下参数按照我理解的重要性排序

  • booster:
    • ‘gbtree’: 使用树模型作为基分类器
    • ‘gbliner’: 使用线性模型作为基分类器
    • 默认使用模型树模型即可,因为使用线性分类器时XGBoost相当于退化成含有L1和L2正则化的逻辑回归(分类问题中)或者线性回归(回归问题中)
  • n_estimators: 基分类器数量
    • 每个分类器都需要一轮训练,基分类器越多,训练所需要的时间越多
    • 经测试发现,开始时越大越能提升模型性能,但是增加到一定程度后模型变化不大,甚至出现过拟合
  • max_depth[default=3]: 每棵树的最大深度
    • 树越深,越容易过拟合
  • objective[default="binary:logistic"]: 目标(损失函数)函数,训练的目标是最小化损失函数
    • ‘binary:logistic’: 二分类回归, XGBClassifier默认是这个,因为XGBClassifier是分类器
    • ‘reg:linear’: 线性回归, XGBRegressor默认使用这个
    • ‘multi:softmax’: 多分类中的softmax
    • ‘multi:softprob’: 与softmax相同,但是每个类别返回的是当前类别的概率值而不是普通的softmax值
  • n_jobs: 线程数量
    • 以前使用的是nthread, 现在已经不使用了,直接使用n_jobs即可
    • 经测试发现并不是越多越快, 猜测原因可能是因为各个线程之间交互需要代价
  • reg_alpha: L1正则化系数
  • reg_lambda: L2正则化系数
  • subsample: 样本的下采样率
  • colsample: 构建每棵树时的样本特征下采样率
  • scale_pos_weight: 用于平衡正负样本不均衡问题, 有助于样本不平衡时训练的收敛
    • 具体调参实验还需测试[待更新]
    • 这个值可以作为计算损失时正样本的权重
  • learning_rate: shrinkage参数
    • 更新叶子结点权重时,乘以该系数,避免步长过大,减小学习率,增加学习次数
    • 在公式中叫做eta, 也就是 \(\eta\)
  • min_child_weight[default=1]: [待更新]
  • max_leaf_nodes: 最大叶子结点数目
    • 也是用于控制过拟合, 和max_depth的作用差不多
  • importance_type: 指明特征重要性评估方式, 只有在booster为’gbtree’时有效
    • ‘gain’: [默认], is the average gain of splits which use the feature
    • ‘cover’: is the average coverage of splits which use the feature
    • ‘weight’: is the number of times a feature appears in a tree
    • ‘total_gain’: 整体增益
    • ‘total_cover’: 整体覆盖率

常用函数

  • feature_importances_:

    • 返回特征的重要性列表
    • 特征重要性可以由不同方式评估
    • 特征重要性评估指标(importance_type)在创建时指定, 使用plot_importance函数的话,可以在使用函数时指定
  • plot_importance: 按照递减顺序给出每个特征的重要性排序图

    • 使用方式

      1
      2
      3
      4
      from xgboost import plot_importance
      from matplotlib import pyplot
      plot_importance(model)
      pyplot.show()
    • 详细定义

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      def plot_importance(booster, ax=None, height=0.2,
      xlim=None, ylim=None, title='Feature importance',
      xlabel='F score', ylabel='Features',
      importance_type='weight', max_num_features=None,
      grid=True, show_values=True, **kwargs):
      """Plot importance based on fitted trees.
      Parameters
      ----------
      booster : Booster, XGBModel or dict
      Booster or XGBModel instance, or dict taken by Booster.get_fscore()
      ax : matplotlib Axes, default None
      Target axes instance. If None, new figure and axes will be created.
      grid : bool, Turn the axes grids on or off. Default is True (On).
      importance_type : str, default "weight"
      How the importance is calculated: either "weight", "gain", or "cover"
      * "weight" is the number of times a feature appears in a tree
      * "gain" is the average gain of splits which use the feature
      * "cover" is the average coverage of splits which use the feature
      where coverage is defined as the number of samples affected by the split
      max_num_features : int, default None
      Maximum number of top features displayed on plot. If None, all features will be displayed.
      height : float, default 0.2
      Bar height, passed to ax.barh()
      xlim : tuple, default None
      Tuple passed to axes.xlim()
      ylim : tuple, default None
      Tuple passed to axes.ylim()
      title : str, default "Feature importance"
      Axes title. To disable, pass None.
      xlabel : str, default "F score"
      X axis title label. To disable, pass None.
      ylabel : str, default "Features"
      Y axis title label. To disable, pass None.
      show_values : bool, default True
      Show values on plot. To disable, pass False.
      kwargs :
      Other keywords passed to ax.barh()
      Returns
      -------
      ax : matplotlib Axes
      """

单调性保证

  • XGBoost自带单调性保证功能:
    • 参数使用示例是monotone_constraints="(1,0,-1,0,0)",表示输出结果随着
      • 第一个参数单调递增
      • 第三个参数单调递减
      • 其他参数不做约束
    • 这个参数的实现逻辑是:
      • monotone_constraints 参数通过在梯度提升树的分裂过程中加入额外的限制来实现单调性。具体来说,在选择最佳分裂点时,XGBoost 不仅考虑分裂的增益(如基尼不纯度减少或均方误差减少),还会检查分裂是否满足指定的单调性约束。如果一个潜在的分裂点违反了单调性约束,那么即使它能带来较大的增益,也不会被选作最佳分裂点。
    • 在现实场景中会出现修改单调特征值以后,模型预测结果为0的问题
      • 表现:实际使用时体现为输出值全是相同的(单调确没有意义)
      • 原因:此时主要原因是数据本身不具有单调性,特别是当label不随着单调特征单调时,容易出现学到的许多区间上模型值相同
      • 测试(对于单调递增场景,单调递减的正常):
        • 测试一:如果样本中存在太多不单调的数据,甚至希望单增,但数据单调递减,则会导致模型预估值随目标特征值变化,基本相同 * 测试二:如果样本中的目标特征和label是满足单调的,但是存在一些随机值,则在某些区间上容易出现单调值,特别是没有见过的区间上,预估值会是完全一致的
        • 注意:测试时,需要限定其他特征都不变,只有当前特征变化才可以,否则无法保证单调性
  • Demo示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import xgboost as xgb
    import numpy as np
    from sklearn.datasets import make_regression
    from sklearn.model_selection import train_test_split
    # 创建一个简单的回归数据集
    X, y = make_regression(n_samples=1000, n_features=5, noise=0.1)
    # 假设我们有5个特征,并且我们知道第一个特征应该与目标变量呈现正相关,
    # 第二个特征应该与目标变量呈现负相关,其余特征没有特定的单调性要求
    monotone_constraints = (1, -1, 0, 0, 0)
    # 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    # 将数据转换为 DMatrix 格式,这是 XGBoost 所需的数据格式
    dtrain = xgb.DMatrix(X_train, label=y_train)
    dtest = xgb.DMatrix(X_test, label=y_test)
    # 定义 XGBoost 参数
    params = {
    'objective': 'reg:squarederror', # 对于回归任务
    'monotone_constraints': str(monotone_constraints) # 应用单调性约束
    }
    # 训练模型
    model = xgb.train(params, dtrain, num_boost_round=100)
    # 预测
    predictions = model.predict(dtest)
    # 打印部分预测结果
    print(predictions[:10])

Python-Jupyter——Jupyter使用笔记


pip 命令与执行环境不同

  • 原因是 pip 执行的是系统的命令行,而系统的命令行默认 shell 环境与 python 环境不同,可以通过下面的代码确认原因:

    1
    2
    3
    4
    5
    6
    # 查看内核的 Python 路径(应正确)
    import sys
    print(sys.executable) # 输出:.conda/envs/xxx_env/bin/python

    # 查看 shell 中的 pip 路径(可能错误)
    !which pip # Linux/Mac
    • 若两者输出不同,则说明是 shell 环境问题
  • 解法一:指定 python 来执行对应的 pip

    1
    2
    import sys
    !{sys.executable} -m pip list
  • 解法二:修改 ~/.bashrc 文件,并重启 Jupyter

    • 待尝试

Ubuntu-Jupyter——修改默认路径

Ubuntu下修改Jupyter的默认路径

  • 经测试,按照本文的方法修改后不一定生效
  • 一个比较优雅的方法是每次进入指定路径,从该路径启动jupyter notebook
    • 这种方法可确保Jupyter根目录为指定目录

查看配置文件

  • 首先查看是已经生成Jupyter的配置文件,默认新装的Jupyter根目录为~/, 是没有配置文件的
    1
    2
    # 查看配置文件命令
    cat ~/.jupyter/jupyter_notebook_config.py

生成配置文件

  • 如果没有配置文件,则首先需要生成新的配置文件

    1
    2
    # 生成配置文件命令
    jupyter notebook --generate-config
    • root用户执行时可能需要按照要求加上参数

编辑配置文件有两种方式

相对路径方式

打开配置文件修改相对目录c.NotebookApp.default_url,这里默认为/tree, 修改成自己想要的地址即可

1
2
3
# /tree表示当前路径pwd, 如下则表示当前终端路径下的/Coding路径
c.NotebookApp.default_url = '/tree/Coding'
# 这种情况以后打开Jupyter时都需要到指定的文件目录下才行,适用于多个jupyter路径的情况

一般使用这种情况时建议直接保留相对目录/tree即可,这样可以在启动Jupyter时直接在那个文件目录下启动

绝对路径方式

打开配置文件配置绝对目录c.NotebookApp.notebook_dir

1
2
# 这种情况下无论在哪里打开都是绝对目录 	
c.NotebookApp.notebook_dir = u'/home/jiahong/JupyterWorkspace'

如果两种情况都配置了,默认以第一中情况为主,因为第一个是redirect的
如果两种情况都没配置,默认等价于配置了c.NotebookApp.default_url = '/tree'

1…383940…61
Joe Zhou

Joe Zhou

Stay Hungry. Stay Foolish.

608 posts
49 tags
GitHub E-Mail
© 2026 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4