Jiahong 的个人博客

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

Maven——maven包管理问题


Maven配置

  • maven 默认配置路径为 \~/.m2/settings.xml
  • 默认项目路径为 \~/.m2/repository
  • maven 包版本号检索: https://mvnrepository.com/

手动下载安装 Maven 包

  • 注:某些包无法通过 maven 自动下载
  • 即使他们在 https://mvnrepository.com/ 中能搜到对应版本号
  • 此时一种解决方案是下载包,对应在~/.m2/repository路径下创建包名和版本号相对应的文件夹,并且拷贝jar到对应的路径下
    • 下面是一个例子
      1
      2
      3
      4
      5
      6
      # 包信息
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
      <version>2.1.6.RELEASE</version>
      # 存储到本地
      ~/.m2/repository/org/springframework/boot/spring-boot-starter-jdbc/2.1.6.RELEASE/spring-boot-starter-jdbc-2.1.6.RELEASE.jar

OpenCV——opencv包安装


oepncv 与 Python 的关系

  • opencv 的兼容性很差,不同 Python 版本对应不同的 opencv 需要对应安装,否则会卡在最后出现错误(卡很久)

    • 比如 Python 3.6 的 opencv-python 版本安装为4.5.4.60参考链接

      1
      2
      pip install opencv-contrib-python==4.5.4.60
      pip install opencv-python==4.5.4.60
    • 即使是一些项目配置好依赖的时候,往往也要自己手动指定版本号安装opencv,否则不能成功


使用homebrew安装依赖

  • homebrew安装一些依赖时,一些包可能会特别慢(特别是gcc等),可以选择一个个分别安装,反而能加快速度,否则可能出现下载失败导致需要全部重新安装的尴尬情况
    • 有时候不用VPN会更快,可尝试

切换国内镜像

  • 有时候能让homebrew下载更快
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cd "$(brew --repo)"                                                                          
    git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git

    cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
    git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git

    cd "$(brew --repo)"/Library/Taps/homebrew/homebrew-cask
    git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-cask.git

    brew update

githubusercontent 访问失败问题解决

问题背景

  • 在安装文件时出现错误

    1
    2
    3
    curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused
    Error: opencv: Failed to download resource "cmake.rb"
    Download failed: https://raw.githubusercontent.com/Homebrew/homebrew-core/82f2aac1cfd7295db3e59240729e5f9d74b0ec51/Formula/c/cmake.rb
  • 经尝试,手动打开链接https://raw.githubusercontent.com/Homebrew/homebrew-core/82f2aac1cfd7295db3e59240729e5f9d74b0ec51/Formula/c/cmake.rb也不行

解决方案

  • 修改 DNS 为8.8.8.8即可
    • 该修改可能造成一些网站不能访问,慎用(用后即使修改)

Mac——环境变量配置.md


Mac环境变量配置文件

  • /etc/profile
    • 全局的
  • ~/.bash_profile
    • 用户自己的,可能需要自己生成
  • 生效方式
    1
    source ~/.bash_profile

Terminal自动导入环境变量

  • 默认Terminal打开后不会导入用户自定义的环境变量

  • 自动导入可以设置为

    • 在~/.zshrc(这个文件没有的话需要自己生成)中添加一行

      1
      source ~/.bash_profile
    • 也可直接在~/.zshrc中直接定义环境变量,使用~/.bash_profile是为了和Linux匹配且方便切换不同的Bash工具

    • 原理:Terminal打开的是zsh工具,这个工具启动时会自动执行~/.zshrc


Idea

  • Idea中Terminal打开后可能不会跟系统一样自动导入环境变量
    • 如果使用的Terminal是zsh的话,也会自动导入
  • 可以自己手动添加(一次添加,以后都可以自动使用)
  • 或者每次打开Terminal后执行source ~/.bash_profile

ML——MLE和MAP的区别举例说明

本文用一个简单的例子在直观上说明极大似然估计与最大后验估计的区别


举例说明

  • 事件定义

    • A = 好好学习
    • B = 作弊
    • C = 班级第一
  • 条件概率

    • P(C|A) = 0.1
    • P(C|B) = 0.5
  • 已知某同学考了年级第一

    • 此时可得概率:
      • P(C) = 1
    • ML(极大似然估计,找一个使得结果发生可能性最大的条件
      计算条件概率P(结果|条件)
      • 参数为e
      • P(C|e = A) = 0.1
      • P(C|e = B) = 0.5
      • 该同学更可能是作弊了
    • 若此时添加先验:
      • P(A) = 0.99
      • P(B) = 0.01
    • MAP(计算后验概率,在结果发生时,最可能是什么产生的?
      计算后验概率:P(条件|结果) ,令P(C)=1
      • P(A|C) = P(C|A)P(A)/P(C) = 0.1*0.99/1 = 0.099
      • P(B|C) = P(C|B)P(B)/P(C) = 0.5*0.01/1 = 0.005
      • 此时可发现该同学更可能是好好学习了

深入分析:MLE与MAP的区别

  • MAP比MLE多考虑了一个先验概率,这个先验概率指明了条件概率的条件(例如 P(C|A)的先验是P(A))
  • MAP的是比较后验概率,ML的是比较条件概率,但是两者本质上都是找一个使得结果发生的最可能的原因
  • MLE可以认为是特殊的MAP
    • ML是先验概率为均匀分布时的MAP(上例中: 若P(A) = P(B), 则MLE等价于MAP)

ML——参数估计MLE-MAP-BEP

极大似然估计(Maximum Likelihood Estimation,MLE)
最大后验概率估计(Maximum a posteriori Estimation,MAP)
贝叶斯估计(Bayesian Parameter Estimation,BPE)


一般理解

  • 极大似然估计(MLE): 频率学派(参数为固定的某个值)
  • 贝叶斯估计(BPE): 贝叶斯学派(参数服从某个分布)
  • 最大后验概率估计(MAP): 一般的书籍认为属于频率学派
    • 个人理解:MAP前半部分是贝叶斯学派,后半部分是频率学派
      • 前半部分认为参数 \(\theta\))有先验分布,此时参数服从一个分布,而不是确定的值,是贝叶斯学派的
      • 后半部分认为参数不是服从后验分布,而是一个具体的使得后验概率最大的值,这里是频率学派的做法
  • 三者的终极目标都是估计模型参数 \(\theta\),MAP和MLE估计参数 \(\theta\) 为具体某个值,BPE估计参数 \(\theta\) 为一个分布
  • 其他贝叶斯网络模型(有向图概率图模型)参数估计的方法还有吉布斯采样,变分推断,EM算法等

极大似然估计与最大后验概率估计

  • 比较MLE与MAP直观理解见我的另一篇博客:MLE-vs-MAP——一个简单的例子说明二者的区别
  • 都只关注参数的具体某个最优值
  • 极大似然估计相当于是参数 \(\theta\) 的先验分布 \(P(\theta)\) 为均匀分布的最大后验概率估计

最大后验概率估计与贝叶斯估计

  • 相似点:
    • 都考虑了参数的先验分布(贝叶斯学派)
    • 最大后验概率估计是贝叶斯估计的一种简化实现(认为 \(\theta\) 都是出现在最可能出现的地方,牺牲一点精度,不用求复杂的分母积分)
    • 二者都围绕下面的公式进行估计
      $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
  • 区别:
    • 贝叶斯估计 :求得的结果估计参数 \(\theta\) 服从一个分布,不能忽略归一化因子 \(P(X)\),此时 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\),贝叶斯估计要计算后验分布,所以需要计算归一化因子,虽然对不同参数值,分母积分结果是相同的,但是计算分布时需要这个归一化因子,否则后续得到的不是分布,也无法求取参数的期望等
    • 最大后验概率估计 :求得的结果估计参数 \(\theta\) 是一个具体的值,把分母 \(P(X)\) 给忽略了,直接对分子极大化求得最优的参数 \(\theta^{\star}\),由于跟贝叶斯估计一样,对不同参数值,分母积分结果是相同的,所以 \(P(X)\) 的值不影响最优参数值的选取【不求参数 \(\theta\) 的分布,所以不用求分母,分母是不影响求参数最优值的】,不用计算归一化因子(很复杂,需要积分),速度会快很多
  • 最大后验概率估计相当于是参数后验分布 \(P(\theta|X)\) 被最可能的参数值 \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)\) 替代的贝叶斯估计
估计模型 目标值 关心对象 求值方式
MLE $$\theta^{\star}=\mathop{\arg\max}_{\theta}(P(X\mid \theta)$$ \(P(X\mid \theta)\) 最大化似然函数 \(P(X\mid \theta)\)
MAP $$\theta^{\star}=\mathop{\arg\max}_{\theta}(P(\theta\mid X)$$ \(P(X\mid \theta)P(\theta)\) 最大化后验概率 \(P(\theta\mid X)=\frac{P(X\mid \theta)P(\theta)}{P(X)}\)
只需最大化分子 \(P(X,\theta)=P(X\mid \theta)P(\theta)\)
BPE \(P(\theta\mid X)\)
(\(\theta\) 的后验概率分布)
\(\frac{P(X\mid \theta)P(\theta)}{P(X)}\) 求参数 \(\theta\) 的后验概率分布 \(P(\theta\mid X)\)
\(P(\theta\mid X)=\frac{P(X\mid \theta)P(\theta)}{\int_{\theta}P(X\mid\theta)P(\theta)d_{\theta}}\)

一个容易理解的角度

  • 参考博客: https://blog.csdn.net/liu1194397014/article/details/52766760

问题描述

  • 已知数据集为 \(X=(x_{1}, x_{2},,,x_{n})\)

  • 极大似然估计

    • 已知数据集 \(X\) 的情况下,求参数最优值 \(\theta^{\star}\),使得似然函数 \(P(X|\theta)\) 最大
  • 最大后验概率估计

    • 已知数据集 \(X\) 的情况下,求参数最优值 \(\theta^{\star}\),使得后验概率 \(P(\theta|X)\) 最大,实际只需使得 \(P(X,\theta)=P(X|\theta)P(\theta)\) 最大
  • 贝叶斯估计

    • 已知数据集 \(X\) 的情况下,求参数 \(\theta\) 的后验分布 \(P(\theta|X)\)

极大似然估计(MLE)

  • 推导
    $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
    • \(P(\theta)\) 的取值与参数 \(\theta\) 无关【认为每个参数 \(\theta\) 出现的概率相等】
      • \(P(\theta)\) 与参数 \(\theta\) 无关可以理解为参数 \(\theta\) 服从均匀分布 : 假设参数 \(\theta\) 有k个离散取值 \(\theta_{1}, \theta_{2},,,\theta_{k}\),那么 \(P(\theta_{1})=P(\theta_{2})=…=P(\theta_{k})=\frac{1}{k}\)
    • \(P(X)\) 的取值与 \(\theta\) 无关,设置为 \(P(X)=1\) 即可
    • 所以得到下面的表达式
      $$\mathop{\arg\max}_{\theta}P(\theta|X)=\mathop{\arg\max}_{\theta}P(X|\theta)$$
      • 式子中 \(P(X|\theta)\) 被称为似然函数
  • 结论
    • 极大似然估计: \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(X|\theta)\)
    • 文字解释: 极大似然估计的目标是找一个参数 \(\theta\),使得在参数 \(\theta\) 对应的概率分布模型下,数据集 \(X\) 出现的概率最大(似然函数最大)

最大后验概率估计(MAP)

  • 推导
    $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
    • \(P(\theta)\) 为的取值与参数 \(\theta\) 相关,是关于 \(\theta\) 的一个先验概率【不同的参数 \(\theta\) 出现的概率可能不同】
      • \(P(\theta)\) 与参数 \(\theta\) 相关可以理解为: 假设参数 \(\theta\) 有k个取值 \(\theta_{1}, \theta_{2},,,\theta_{k}\),那么 \(\sum_{i=1}^{k}P(\theta_{i})=1\),但 \(P(\theta_{1}),P(\theta_{2}),,,P(\theta_{k})\) 的取值不能确定,也不一定相等
    • \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\) 积分结果与 \(\theta\) 不相关,分母的值不影响后验概率最大值的参数值,直接忽略(设置为 \(P(X)=1\))即可
    • 所以得到
      $$\mathop{\arg\max}_{\theta}P(\theta|X)=\mathop{\arg\max}_{\theta}P(X|\theta)P(\theta)=\mathop{\arg\max}_{\theta}P(X,\theta)$$
  • 结论
    • 最大后验概率估计: \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(X|\theta)P(\theta)\)
    • 文字解释: 最大后验概率估计的目标是找一个参数 \(\theta\),使得在参数 \(\theta\) 服从已知先验分布 \(P(\theta)\) 和数据集 \(X\) 的情况下,对应的后验概率 \(P(\theta|X)\) 最大(等价于 \(P(X,\theta)=P(X|\theta)P(\theta)\) 最大)

贝叶斯估计(BPE)

  • 推导
    $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
    • \(P(\theta)\) 为的取值与参数 \(\theta\) 相关,是关于 \(\theta\) 的一个先验概率
      • \(P(\theta)\) 与参数 \(\theta\) 相关可以理解为: 假设参数 \(\theta\) 有k个取值 \(\theta_{1}, \theta_{2},,,\theta_{k}\),那么 \(\sum_{i=1}^{k}P(\theta_{i})=1\),但 \(P(\theta_{1}),P(\theta_{2}),,,P(\theta_{k})\) 的取值不确定,也不一定相等
    • \(P(X)\) 的取值与 \(\theta\) 本身不相关,但是为了求出后验分布 \(P(\theta|X)\), \(P(X)\) 作为归一化因子需要计算
      • \(P(X)\) 的值与参数的先验分布,模型的定义(高斯分布还是贝塔分布等)和数据集 \(X\) 有关系
      • 没有分母作为归一化因子的话单独的分子是联合分布 \(P(X,\theta)\),这个分布对 \(\theta\) 积分结果不为1(而是 \(P(X)\)),联合分布不能确定 \(\theta\) 的后验分布
      • \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\)
    • 所以得到
      $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{\int_{\theta}P(X|\theta)P(\theta)d_{\theta}}$$
  • 结论
    • 贝叶斯估计: \(P(\theta|X)=\frac{P(X|\theta)P(\theta)}{\int_{\theta}P(X|\theta)P(\theta)d_{\theta}}\)
    • 文字解释: 贝叶斯估计的目标是求参数的后验分布 \(P(\theta|X)\),参数 \(\theta\) 服从先验分布 \(P(\theta)\),在已知数据集 \(X\) 修正后,参数 \(\theta\) 的后验概率分布为 \(P(\theta|X)\)
  • 缺点
    • 计算 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\) 比较耗时

一个更深入的理解

问题描述

  • 已知数据集为 \(X=(x_{1}, x_{2},,,x_{n})\),新数据集为 \(D=(d_{1}, d_{2},,,d_{m})\)
  • 求已知数据集 \(X\) 的情况下,假设数据集 \(X\) 由某个模型M(参数为 \(\theta\))生成,那么数据集 \(D\) 也由模型M生成的概率 \(P(D|X)\)
    • 模型M的确定因素:
      • 由三个因素唯一确定
        • 参数 \(\theta\) 的先验分布 \(P(\theta)\)
        • 模型的类型定义 \(f(\theta)\) (高斯分布,贝塔分布,二项分布还是其他什么分布)
        • 模型的已知观察数据集 \(X\)
      • 由两个因素唯一确定
        • 模型的类型定义 \(f(\theta)\) (高斯分布,贝塔分布,二项分布还是其他什么分布)
        • 参数 \(\theta\) 的后验分布 \(P(\theta|X)\)
  • 另一种表述: 用模型M(参数为 \(\theta\))生成数据,在已观察到模型M生成了数据集 \(X\) 后,预测模型M接下来生成数据集 \(D\) 的概率

极大似然估计(MLE)

  • 特点:假设模型M(参数 \(\theta\))没有先验分布

  • 模型参数估计

    • 模型参数为一个确定的最优值
    • \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(X|\theta)\)
  • 概率计算

    • \(P(D|X)=P(D|\theta^{\star})\)
  • 优点

    • 计算速度快
  • 缺点

    • 不够精确,特别是当观察到的数据集 \(X\) 太小时,这种情况不考虑参数的先验分布可能会造成过拟合
      • 举例: 判断一个学校男女比例,在观察到两个男生,一个女生走出校门后就判断男女比例为2:1显然不合适
        • 注意:单个同学是男生或者女生的概率服从伯努利分布,多个同学中男生的数量服从二项分布,整个学校的某个学生是男生的概率服从贝塔分布

贝叶斯估计(BPE)

  • 特点:假设模型M(参数 \(\theta\))有先验分布 \(P(\theta)\),计算观察到数据集 \(X\) 后 \(\theta\) 的后验分布 \(P(\theta|X)\),然后求 \(P(D|\theta)\) 关于后验分布 \(P(\theta|X)\) 的期望(这个期望也就是模型M生成数据集 \(D\) 的概率)
    • 这里可以理解为观察到的数据集是对先验分布的修正,修正后的后验分布会更符合模型实际情况(因为先验分布很可能是瞎猜的)
  • 模型参数估计
    • 模型参数为一个分布
    • \(P(\theta|X)=\frac{P(X|\theta)P(\theta)}{\int_{\theta}P(X|\theta)P(\theta)d_{\theta}}\)
    • 分子为归一化因子 \(P(X)\)
      • 必须计算,该值与参数的先验分布 \(P(\theta)\),模型的类型定义(\(f(\theta)\))以及数据集 \(X\) 有关系,不计算 \(P(X)\) 的话后面计算得到的 \(P(D|X)\) 也将是一个不确定的值(不是概率值,是 \(P(X)\) 的函数)
  • 概率计算
    • \(P(D|X)=\int_{\theta}P(D,\theta|X)d_{\theta}=\int_{\theta}P(D|\theta,X)P(\theta|X)d_{\theta}=\int_{\theta}P(D|\theta)P(\theta|X)d_{\theta}\)
      • 式子中 \(P(D|\theta,X)=P(D|\theta)\),在通过 \(X\) 确定 \(\theta\) 后模型也就确定了, \(X\) 不会继续影响 \(D\) 的生成
    • 这里 \(P(D|X)\) 相当于 \(P(D|\theta)\) 关于后验分布 \(P(\theta|X)\) 的期望
  • 优点
    • 计算结果最精确,能根据参数的先验分布和数据集 \(X\) 的知识,准确计算模型生成数据集 \(D\) 的概率
  • 缺点
    • 计算 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\) 比较耗时,不常用
关于 \(P(X)\) 是否需要计算?
  • 无需计算的情况
    • 判断两个数据集 \(D_{1},D_{2}\) 由同一个模型M生成的概率谁大,可以不用计算 \(P(X)\)
      • 因为对于同一模型M, \(P(X)\) 相同大小,此时只需要比较 \(P(D_{1},X)\) 和 \(P(D_{2},X)\) 谁大即可知道 \(P(D_{1}|X)\) 和 \(P(D_{2}|X)\) 谁大
  • 必须计算的情况
    • 判断数据集 \(D\) 由两个模型 \(M_{1},M_{2}\) 生成的概率谁大,必须计算 \(P(X)\)
      • 因为对于不同模型 \(M_{1},M_{2}\), \(P(X)\) 不相同【每个模型生成 \(X\) 的概率不同】,此时仅仅比较 \(P(D_{1},X)\) 和 \(P(D_{2},X)\) 谁大不能确定 \(P(D_{1}|X)\) 和 \(P(D_{2}|X)\) 谁大
    • 利用模型M采样生成新数据(预测问题),必须计算 \(P(X)\)
      • 这时候每次采样时需要根据参数 \(\theta\) 的后验分布采样生成 \(\theta_{i}\),然后再根据 \(\theta_{i}\) 确定的模型 \(M_{i}\) 采样生成观测数据,两次采样的过程都必须知道准确的分布(积分为1,也就是归一化后的),所以此时必须计算 \(P(X)\)

最大后验概率估计(MAP)

  • 特点:假设模型M(参数 \(\theta\))有先验分布 \(P(\theta)\),但不计算模型的后验分布 \(P(\theta|X)\),只用最可能的 \(\theta\) 代替后验分布来确定模型M

  • 模型参数估计

    • 模型参数为一个确定的最优值
    • \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)=\mathop{\arg\max}_{\theta}P(X|\theta)P(\theta)\)
      • 这里与贝叶斯估计作对比可以发现,MAP相当于把参数后验分布简化为最可能的那个参数值,用最可能的参数值代替参数后验分布 ,这样做对最终预测结果 \(P(D|X)\) 可能有点误差,但是不用计算复杂的积分 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\)
      • 这里能够用最优值替代分布的前提是分布是很集中的(也就是要 \(P(\theta|X)\) 方差小,比如贝塔分布,狄利克雷分布和高斯分布等钟型分布的塔尖要尖),不然误差可能会比较大
      • 注意后验分布 \(P(\theta|X)\) 最可能值的参数值是概率最大的地方 \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)\),而不是参数 \(\theta\) 关于后验分布的期望 \(\mathbb{E}_{P(\theta|X)}[\theta]=\int_{\theta}\theta P(\theta|X)d_{\theta}\) (期望对应平均值,而不是最可能的值 ,特例:对称钟型分布的期望同时也是它最可能的值)
  • 概率计算

    • \(P(D|X)=P(D|\theta^{\star})\)
  • 计算速度和精确度都介于MLE和BPE之间


总结

  • 贝叶斯估计可以退化成最大后验概率估计
    • 最大后验概率估计相当于是参数后验分布 \(P(\theta|X)\) 被最可能的参数值 \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)\) 替代的贝叶斯估计
  • 最大后验概率估计可以退化成极大似然估计
    • 极大似然估计相当于是参数 \(\theta\) 的先验分布 \(P(\theta)\) 为均为分布的最大后验概率估计

MySQL——数据库导入导出

参考博客: https://blog.csdn.net/u013626215/article/details/88548342


从MySQL中导出数据库信息

  • 导出所有表结构

    1
    mysqldump -h [host_ip] -u [user_name] -p -d [db_name] > [file_name]
  • 导出所有表结构和数据

    1
    mysqldump -h [host_ip] -u [user_name] -p [db_name] > [file_name]
  • 导出某一张表结构

    1
    mysqldump -h [host_ip] -u [user_name] -p -d [db_name] [table_name] > [file_name]
  • 导出某一张表结构和数据

    1
    mysqldump -h [host_ip] -u [user_name] -p [db_name] [table_name] > [file_name]

导入数据库到MySQL

  • 登录数据库

    1
    mysql -h [host_ip] -u [user_name] -p
  • 执行导入命令

    1
    source [file_name]
  • 注意: 数据导入需要提前创建数据库

Python——Copy-and-Deepcopy

deepcopy 与 copy 的本质区别——是否为可变对象创建新的对象(内存空间)
以下图片截取自Python Tutorial


代码片段一

  • 可变对象 list 中包含着可变 list 和不可变对象 tuple,且 tuple 中不包含可变对象
    1
    2
    3
    4
    5
    import copy
    l1 = [3, [66, 55, 44], (7, 8, 9)]
    l2 = list(l1) # <==> l2 = copy.copy(l1)
    # <==> l2 = l1[:]
    l3 = copy.deepcopy(l1)

代码片段二

  • 可变对象 list 中包含着可变 list 和不可变对象 tuple, 且tuple中包含可变对象list
    1
    2
    3
    4
    5
    import copy
    l1 = [3, [66, 55, 44], (7, 8, [1, 2])]
    l2 = list(l1) # <==> l2 = copy.copy(l1)
    # <==> l2 = l1[:]
    l3 = copy.deepcopy(l1)

代码片段三

  • 不可变对象中包含可变对象
  • 值得强调的是,copy 复制 tuple时,不会像 list 那样直接创建新对象,无论 tuple 中是否有可变对象
  • 除非包含不可变对象,否则 deepcopy 复制 tuple 时也不会创建新对象
    1
    2
    3
    4
    5
    6
    7
    import copy
    t1 = (3, [66, 55, 44], (7, 8, [1, 2]))
    t2 = t1
    t3 = tuple(t1) # <==> t4 = t1[:]
    # t5 = copy.copy(t1)
    t6 = copy.deepcopy(t1)
    t1[1].append(100)

copy和deepcopy直接对比

  • copy.copy()是浅拷贝,copy.deepcopy()是深拷贝

浅拷贝 (copy.copy())

当你使用 copy.copy() 函数时,它会创建一个新对象,然后将原始对象中包含的所有元素引用都复制到这个新对象中。这意味着如果你修改了原对象中的可变元素(如列表、字典等),那么副本中的这些元素也会受到影响,因为它们实际上是指向同一个内存位置的引用

  • 浅拷贝示例:

    1
    2
    3
    4
    5
    6
    7
    import copy
    original_list = [[1, 2], [3, 4]]
    shallow_copy = copy.copy(original_list)
    original_list[0][0] = 'changed'

    print(original_list) # 输出: [['changed', 2], [3, 4]]
    print(shallow_copy) # 输出: [['changed', 2], [3, 4]]
    • 在这个例子中,对 original_list 的修改也影响到了 shallow_copy,因为子列表是被引用的,而不是被复制的

深拷贝 (copy.deepcopy())

  • copy.deepcopy() 函数则不仅复制了对象本身,还递归地复制了对象中包含的所有对象。因此,新的对象及其包含的所有对象都是完全独立的,对原对象或其内部对象的任何改变都不会影响到深拷贝后的对象

  • 深拷贝示例:

    1
    2
    3
    4
    5
    6
    7
    import copy
    original_list = [[1, 2], [3, 4]]
    deep_copy = copy.deepcopy(original_list)
    original_list[0][0] = 'changed'

    print(original_list) # 输出: [['changed', 2], [3, 4]]
    print(deep_copy) # 输出: [[1, 2], [3, 4]]
    • 在这个例子中,对 original_list 的修改不会影响到 deep_copy,因为所有级别的对象都被复制了

总结

  • 对于不可变对象调用 deepcopy 和 copy 函数时:
    • deepcopy 与 copy 操作一样,都不为创建新对象,而是直接引用
    • 在后面如果有修改该不可变对象的操作时再创建新对象,此时两个版本的不可变对象地址变得不同
    • 这里是 Python 的常态,比如tuple(tuple1)将返回一个 tuple1 对象的引用而不是副本,当修改 tuple1 时才会创建新对象
    • 因为无论如何,修改不可变对象的不可变部分都不会修改原始对象,所以为了节约内存,Python 解释器完全可以将创建新对象延后到修改内容时
  • 对于可变对象调用 deepcopy 和 copy 函数时:
    • 使用 copy.copy() 只复制对象的第一层,对于对象内部的嵌套对象只复制引用
    • 使用 copy.deepcopy() 会递归地复制整个对象结构,包括所有的嵌套对象,从而确保两个对象完全独立。

LaTex——排版

vspace

  • 增加或减少行间距
  • 例如,减少图片和正文的间距0.1cm采用下面的表达,单位可以是cm,pt,mm等
    1
    2
    3
    4
    5
    6
    7
    8
    \begin{figure}[h]
    \centering
    \vspace{-0.1cm}
    \includegraphics[width=\linewidth]{Q-Network-Page-2}
    \caption{Q-Network of RL-MPCA}
    \Description{}
    \label{fig:Q-Network}
    \end{figure}

列表缩进

  • 参考链接:
    • https://tex.stackexchange.com/questions/170525/itemize-left-margin
    • https://www.cxyzjd.com/article/robert_chen1988/83179571
  • 缩进设置
    1
    2
    % \usepackage{enumitem}
    % \setlist{leftmargin=5.5mm}

footnote编号

  • \footnote{}默认会自动编号,整片文章按照顺序排列编号
  • \footnote[3]{}则允许手动设置编号,可以按照自己的意愿随意设置编号

超链接

  • 参考链接:
  • 文档内部超链接
    1
    2
    3
    \usepackage{hyperref}
    \hyperlink{thesentence}{[1]}
    \hypertarget{thesentence}{[1]}.

Ubuntu——ElasticSearch安装与配置(logstash)

ElasticSearch的安装与基本配置


安装ElasticSearch

  • 下载ElasticSearch deb安装包
  • 安装ElasticSearch
    • Ubuntu中默认安装路径为/usr/share/elasticsearch/
  • 配置ES为一个服务
    1
    2
    sudo /bin/systemctl daemon-reload
    sudo /bin/systemctl enable elasticsearch.service

启动ElasticSearch

1
sudo systemctl start elasticsearch.service

启动相关问题

  • 设置远程访问:
    • 修改config/elasticsearch.yml中network.host : 0.0.0.0
  • 可能遇到的问题1:

[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

  • 解决方案:https://www.cnblogs.com/chenjiangbin/p/12060899.html
  • 可能遇到的问题2:

[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]

  • 解决方案:https://blog.csdn.net/python36/article/details/84257343
  • 可能遇到的问题3:

[1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured

  • 解决方案:https://www.cnblogs.com/hellxz/p/11057234.html

关闭ElasticSearch

1
sudo systemctl stop elasticsearch.service

ElasticSearch的使用

ES的使用可从官网上查看,点击下一步接着可看完整个流程
*操作ES接口时,建议使用postman *

查看索引

1
GET /_cat/indices?v

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size

创建索引

1
2
# 创建一个名字为customer的Index
PUT /customer?pretty

添加数据

给Index添加Document数据

1
2
3
4
5
6
# 向customer Index中添加id为1的Document
# 内容为{"name": "John Doe"}
PUT /customer/_doc/1?pretty
{
"name": "John Doe"
}

如果是使用Postman,这里选择json类型即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}

查询数据

1
2
# 从customer中查询id为1的数据
GET /customer/_doc/1?pretty
1
2
3
4
5
6
7
8
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : { "name": "John Doe" }
}

删除索引

1
2
# 删除名为customer的索引
DELETE /customer?pretty

修改数据

1
2
3
4
5
6
7
# 向customer Index中添加id为1的Document
# 如果目标Document已经存在,则修改目标Document为指定的数据
# 内容为{"name": "John Doe"}
PUT /customer/_doc/1?pretty
{
"name": "Joe Doe"
}

使用logstash同步数据

6.2.4同步mysql数据到ES

安装logstash

  • 下载logstash 6.2.4
    • 为了方便配置管理,建议下载zip或者tar.gz版本
  • 解压到指定文件夹,建议在相关项目下创建ElasticSearch文件夹,并存储以下数据
    • logstash 解压文件夹logstash-6-2-4
    • 新建文件: logstash更新 mysql 数据库索引到 ES 时的配置文件,一般命名为mysql.config [后面会给出详细内容]
    • 下载jdbc库: mysql-connector-java.jar [用于连接数据库]
      • 这里下载Platform Independent的压缩包版本解压即可找到需要的jar包

配置文件及jdbc连接库

  • 新建一个名为mysql.config的文件,内容为

    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
    # logstash-6.2.2\bin\logstash.bat -f mysql.config
    # logstash-6.2.4/bin/logstash -f mysql.config
    input {
    jdbc {
    # mysql jdbc connection string to our backup databse
    jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/docker_manager?serverTimezone=UTC"
    # the user we wish to excute our statement as
    jdbc_user => "docker"
    jdbc_password => "123456"
    # the path to our downloaded jdbc driver
    jdbc_driver_library => "/home/jiahong/Workspace/IdeaProjects/DockerManagerSystem/elastic-search/mysql-connector-java-8.0.11.jar"
    # the name of the driver class for mysql
    jdbc_driver_class => "Java::com.mysql.jdbc.Driver"
    # jdbc_paging_enabled => "true"
    # jdbc_page_size => "50000"
    # statement_filepath => "jdbc.sql"
    schedule => "* * * * *"
    # type => "jdbc"
    statement => "SELECT * FROM docker_manager.DockerManager_docker WHERE id > :sql_last_value"
    use_column_value => true
    tracking_column => "id"
    }
    }

    output {
    elasticsearch {
    hosts => "127.0.0.1:9200"
    index => "docker"
    document_id => "%{id}"
    }
    }
    • 关于mysql.config,一般需要配置的地方为:
      • jdbc_connection_string: 注意docker_manager为数据库名,后面的时区参数有时也需要修改,关于时区的问题可我的博客
        Linux——Logstash时区问题
      • jdbc_driver_library: 这里需指定到对应的jdbc连接库
      • statement: 数据库查询语句
      • jdbc_user: 数据库用户名l
      • jdbc_password: MySQL用户名对应的密码
      • hosts: 输出到ES地址
      • index: ES服务器的Index(相当于MySQL中的数据库)

利用logstash同步mysql数据库数据到ES

  • 启动同步操作
    1
    2
    3
    4
    # 进入之前创建用于解压logstash源文件的目录下
    cd ElasticSearch
    # 启动同步
    ./logstash-6.2.4/bin/logstash -f mysql.config

一旦同步开始,如果不关闭进程,那么将一直自动同步,建议同步完成(当输出不再变化)后关闭进程

  • 查看ES中相应的Index是否已经被更新

Ubuntu——屏幕亮度调节

Ubuntu屏幕亮度调节


Flux

  • Flux是一款非常好用的屏幕调整软件,不仅可以调整屏幕亮度,还能调整色调等
  • 但是,许多Ubuntu版本下,Flux都不能使用,还会影响apt-get update命令,一般情况下,都会将其从表中删除
    • 如果Flux可以使用,建议优先使用Flux

xrandr调整屏幕亮度

  • 展示已有屏幕

    1
    xrandr -q
    • 或者可以使用更简洁的版本
      1
      xrandr -q | grep " connected"
  • 调整指定屏幕的亮度

    1
    xrandr --output HDMI-0 --brightness 0.5
    • 其中HDMI-0是屏幕名称,0.5是亮度参数,大于1时屏幕会发白,注意不要调整的太亮
  • 说明:xrandr修改的屏幕亮度在重启电脑后不会保存,如果想要每次开机自动调整,可以在开机启动添加脚本

1…575859…64
Joe Zhou

Joe Zhou

Stay Hungry. Stay Foolish.

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