anaconda create environment with yaml 创建python虚拟环境报错

anaconda是一个开源的Python发行版本,它可以创建python程序运行的虚拟环境,我们通过之前的文章经介绍过anaconda的安装及基本命令的使用方式。

1、anaconda 导出虚拟环境的步骤和命令

首先,切换到要导出的名字叫做vir_base的环境下, source activate vir_base

然后通过命令 conda env export > ./environment.yaml 把所有环境导出到 当前路径下的 environment.yaml 文件中, 文件内的大概内容如下,

anaconda 导出的yml文件内容

2、在新机器上生成或者更新环境

如果直接通过yaml文件生成环境,则直接通过命令

conda env create -f environment.yaml -p /data/anaconda/env/vir_base

注: -p 是指定安装目录,也可以不带这个参数;不带参数会按照yaml文件带的路径来安装

如果已经提前手动创建了虚拟环境,只是想通过yaml文件来更新环境,则先切换到虚拟环境下, source activate vir_base

然后通过命令 conda env update –file environment.yaml 来更新当前环境

3、遇到的错误

无论是create 或者update环境的时候不断输出如下的提示,

Warning: you have pip-installed dependencies in your environment file, but you do not list pip itself as one of your conda dependencies. Conda may not use the correct pip to install your packages, and they may end up in the wrong place. Please add an explicit pip dependency. I’m adding one for you, but still nagging you.

主要的问题是在yaml或者yml文件中的dependencies 结构下添加pip版本号,如下图报错误是因为 在 1 的位置没有pip版本号,2的位置有,只需要把2 位置的pip版本号复制到上一层的路径下,再次使用文件就不会出错了。

conda环境创建错误处理

bitmap 基本原理介绍及基本应用 python 代码实现

一、 bitmap 是什么东东

简单且抽象来说bitmap用一个bit位来标记某个元素所对应的value,而key就是该元素。而它主要用来解决海量数据中元素查询,去重、以及排序等问题。

二、基本概念梳理

#  存储单位
#  换算的方式GB=>MB=>KB=>Byte=>Bit
#  1、 1 G = 1024 M ; 1M = 1024 KB; 1 KB = 1024 Bytes ; 1 Byte = 8 bit
#  2、 1 G = 1024 M = 1024 * 1024 KB = 1024 * 1024 * 1024 Byte = 1024 * 1024 * 1024 * 8 bit
#  3、 1024 = 2^10 --> 1GB = 2^30 bit

一个整数型的数字在一台31位的计算机中占4个字节,也就是32个bit;而bitmap算法就是用对应的32个bit位来表示十进制的0-31个数。

比如这么一个场景:有一台内存为 2 GB 的 PC,其硬盘中的一个存储了 30 亿个无符号整型数据文件(数据无重复),我们要对其进行排序。

我们来简单估算一下,这个数据文件的大小为 2 * 3 * 10^9 /2^30 约为 5.6 GB,,而我们的计算机就只有2G的内容,显然将这个数据文件直接读入内存是办不到的。我们来看一下如果用bitmap的思想,假设能用一个 bit 位来标示一个 int 整数,30亿个整数需要的内存空间为 3 * 10^9/8/2^20 大概为 357.6 MB,这样需要的存储空间将大大减少,我们可以轻易将这 30 亿个 int 数放到内存中进行排序了。

具体的做法就是,申请一个 int 长度为 N//32 + 1 的数组。N 表示要进行查找的最大整数,我们可以遍历一轮数据获得,通过数组中的每个元素在内存在占 32 位对应表示十进制数 0-31,如何在用bit表示这个具体的数字就是将二进制中对应该自然数字的位置的值设置成1即可。

array[0] 可表示 0-31
array[1] 可表示 32-63
array[2] 可表示 64-95

思想相对比较简单,关键是十进制和二进制bit位需要一个 map 映射表,把10进制映射到bit位上。

(1)如何确定十进制的数值在数组的那个位置?也就是数组的下标该怎么计算。基本公式是 loc_index = (int_value <= N / 32) ,loc_index即为n对应的数组下标,什么意思呢?就是用数字去除一个32,然后取不大于结果的最大整数。例如n = 59, 则 59 / 32 = 1.84375,而不大于1.84的最大整数是1 ,因此59在a[1]中。

(2)接下来是确定一个数字在对应数组内的bit位置。利用的是求模公式;同样的数字59 bit_loc = N % 32 ,例如 n = 59, bit_loc = 59 % 32 = 27

三、python 知识回顾

python世界中10进制转换成其他进制的内置函数
# 1、十进制转二进制:bin(10) --> 输出:'0b1010' 前缀:是字符串类型 0b:表示2进制
# 2、十进制转八进制:oct(10) --> 输出:'0o12'   前缀:是字符串类型 0o:表示8进制
# 3、十进制转十六进制:hex(10) --> 输出:'0xa'  前缀:是字符串类型 0x:表示16进制
#    可以通过format函数把输出的前缀去掉,例如 format(64, 'b') --> 1000000 或者 '{:b}'.format(64) --> 1000000
#   '{:o}'.format(10) --> 12 ;'{:x}'.format(10) -->a
注意: 到bin函数返回二进制数字表示的形式是采用了负号,而不是补码的形式。通过 bin(-27 & 0b1111111111111111)
<< 运算数的各二进位全部左移若干位; >> 运算数的各二进位全部右移若干位
# print(64 << 2) --> 256
# 移动过程逻辑上解释:
#   我们通过函数 format(64, 'b') --> 1000000;其实二进制 1000000 相当于 1000000.0, 小数点位在末尾直接省略了形式;
#   我们上学时学习的时候听到过这样一种描述:数字的左移相当于小数点位的右移,所以 1000000.0 小数点位右移两位变成 100000000.0
#   再次通过二进制转换十进制 int('0b100000000', 2) --> 256
#   print(64 >> 2) --> 16
#   同样的道理 1000000.0 的数字右移相当于小数点位左移, 1000000.0 左移小数点变成了 10000.00; 我们不用函数直接用数学的逻辑来做转换
#   1 * 2^4 + 0 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0  = 16
取模, 除法
#  1、二进制的基础上,与n取模其实就是和n-1相与 ;a%(2^n) 等价于 a&(2^n-1),而&操作比%操作具有更高的效率
#  2、“ / ” 为浮点数除法,返回浮点结果 ; “ // ” 表示整数除法,返回不大于结果的一个最大整数
#    print(10 / 3) --> 3.333333; print(10 // 3) --> 3
class BitMap2(object):
    def __init__(self):
        self.n = 5
        self.bitsize = 1 << self.n
        self.typecode = 'I'  
        self.lowerbound = 0  # 若数组中有负数,则所有数都减去最小的那个负数

    def load(self, inp):
        mini = min(inp)
        if mini < 0:
            self.lowerbound = -mini  # 如果数组中有<0的数,则所有数都要减去最小的那个负数
            inp = [i + self.lowerbound for i in inp]
        maxi = max(inp)
        # 确定数字在数组中的位置
        num_arr = math.floor(maxi / self.bitsize) + 1
        self.arr = array(self.typecode, [0] * num_arr)
        for x in inp:
            self._set(x)

    def _set(self, x):
        '''
        将x在数组中对应元置为1
        '''
        arr_idx = x >> self.n  # 元素在第几个数组中,等价于x // 2**self.n
        bit_idx = x & (self.bitsize - 1)  # 元素在相应数组中的第几个bit位,等价于x % 2**self.n
        self.arr[arr_idx] |= 1 << bit_idx  # 在这个数组里的不断的累加 2**n 最终的结果其实就是二进制转换成十进制的值

    def search(self, x):
        if self.lowerbound != 0:
            x += self.lowerbound
        arr_idx = x >> self.n
        bit_idx = x & (self.bitsize - 1)
        # 这里有问题,正常情况需要做数组长度的前置验证逻辑
        existence = True if self.arr[arr_idx] & (1 << bit_idx) else False
        return existence

    def sort(self):
        sorted_seq = []
        for arr_idx, a in enumerate(self.arr):
            for bit_idx in range(self.bitsize):
                if a & (1 << bit_idx):
                    sorted_seq.append(arr_idx * self.bitsize + bit_idx - self.lowerbound)
        return sorted_seq

if __name__ == '__main__':
    bitMap = BitMap()
    bitMap.load([3, 2, 4])
    print(bitMap.search(3))

异常处理 Your PyTorch installation may be too old 运行时错误 版本过低的处理过程

在之前的文章中我们介绍过anaconda的安装和基本入门使用。笔者遇到的问题是在anaconda虚拟环境运行程序是出现的。其实本篇并不是pytorch相关的知识点介绍,只是针对一个异常处理的过程总结。

1、异常背景

笔者在gayhub上嫖到一个自动写文章的源码,扒下来学一波,于是在Linux服务器上搭建了代码所遇的python环境,根据requirements.txt的内容安装所有需要的包,原作者只做基本环境做了python3.6的要求,所以笔者用anaconda 构建虚拟环境的时候直接安装python==3.6.0的环境,同样在这个基础上安装了pytorch的包(pytorch==1.4.0)

2、异常发生

环境构建完成后运行代码就出现了那个常规错误。类似于如下的输出

Traceback (most recent call last):
  File "demo.py", line 76, in <module>
    demo(args)
  File "demo.py", line 45, in demo
    model.load_state_dict(torch.jit.load(args.model))
  File "/home/simon/anaconda3/envs/raft/lib/python3.6/site-packages/torch/jit/__init__.py", line 146, in load
    torch._C.import_ir_module(module_lookup, f, map_location, _extra_files)
RuntimeError: version_number <= kMaxSupportedFileFormatVersion ASSERT FAILED at /pytorch/caffe2/serialize/inline_container.cc:131, please report a bug to PyTorch. Attempted to read a PyTorch file with version 3, but the maximum supported version for reading is 1. Your PyTorch installation may be too old. (init at /pytorch/caffe2/serialize/inline_container.cc:131)

这个异常已经给出了最本质的问题所在,其实就是你运行的代码是用更高版本的pytorch语法写的,但是你现在的环境pytorch的版本过低。

一般来说,是有两个处理方案的: 一是修改你的代码运行环境,二是修改代码的写法。如果修改代码的写法,主要是比对pytorch==1.4.0与pytorch==1.7.0 +的差异就可以了,版本之间的写法造成了该异常的发生,修改代码兼容性就可以避免这个问题。

但是笔者是在嫖别人的源码,首次环境错误不太好直接修改代码,万一越来越碎就狗带了。所以笔者直接把anaconda的环境删掉了,安装了python==3.6.9,在这个python环境的基础上安装pytorch,此时已经pytorch==1.9.0了,这个问题直接规避掉。