## 这个文件是关于ros、linux指令,pytorch、python、onnx和相关problem的一些笔记
### ROS && linux
 **find: 在当前路径或指定的路径下递归地搜索文件或目录,并可以根据不同的条件进行过滤和匹配。**
```
     find -name *.py find /home/dai/bev_lane_det-main -name models  find /home/dai/bev_lane_det-main -mtime -1(查找最近修改的文件)
 ```
**locate:在系统的文件数据库中快速查找文件或目录,只要在路径中包含该文件或目录,就会返回这个路径,而不是实时搜索文件系统。常比 find 命令快速,但可能不会返回最新创建或修改的文件。**
```
 都不带*,且无法加指定路径,它是自己全文搜索:  locate single_camera_bev    locate libprotoc
 ```
**whereis:查找系统中某个可执行程序,即命令的位置、源代码文件和帮助文档,也就是bin下的文件等等**
```
     whereis ls
 ```
**which:查找系统中某个可执行程序,即命令的位置,也就是bin下的文件**
```
     which ls
 ```
 gnome-session-properties 开机自启
 `catkin_make -DPYTHON_EXECUTABLE=/usr/bin/python3`
`src目录下:catkin_create_pkg sys_time roscpp rospy std_msgs`
 **ros中的rospy使用虚拟环境、包的方法:**
```
 #!/home/dai/anaconda3/envs/clrnet/bin/python
     import sys
     sys.path.append('/home/dai/anaconda3/clrnet/lib/python3.8/site-packages');
     终端运行时要conda activate clrnet
     其cmake中(不用excutable、target_link):
         catkin_install_python(PROGRAMS
           scripts/rstest.py
           scripts/sub.py
           scripts/tes.py
           DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
         )
         add_message_files(  ##(ros_laneatt、robotyolo的cmake中有)
           FILES
             Xyz_Boundings.msg
             Xyz_Boundings_List.msg
         )
 ```
    此时若是py:from rsyolo.msg import Xyz_Boundings   若是cpp:#include <rsyolo/Xyz_Boundings_List.h>(因为自己会生成devel下面的.h文件)
     注意:回调函数原型中的指针参数:表示指向消息对象的指针,而不是对象地址的指针
 cmake.. 生成makefile, make:在文件夹内构建,sudo make install,安装在系统内(好处: 为了好找,同时可以删除源码包了),有时候可以就安装文件夹内(不影响系统可多版本,cmake找的时候就:    set (FCL_DIR "/home/dai/fcl-0.6.0")
         include_directories(${FCL_DIR}/include)
         link_directories(${FCL_DIR}/build/lib)
         find_package(fcl REQUIRED)
 )
 grep -R "ContainerAllocator" /home/dai/ros_deploy_lanedec/ROS_LaneDetection/src/ROS_LaneATT/ | grep -v "<ContainerAllocator>"  搜索包含"ContainerAllocator"的行,然后过滤掉包含"<ContainerAllocator>"的行。
 grep -rn "@TRANSFORMER" /home/dai/LATR-main/  想查找文件中包含 "@transformer" 文本的文件
     -r 选项表示递归搜索,它会搜索指定目录下的所有子目录。
     -n 显示匹配得到的具体的行数
     -l 选项表示仅列出包含匹配文本的文件的名称,而不显示匹配的具体行。
 创建软链接: 可用于数据集等的链接,不用再复制过来了省了空间:
     cd new_workspace/data/
     ln -s /home/dai/bev_lane_det-main/dataset/apollo/data_splits/
 find /etc -name passwd | ls -l  |表示管道符,表示将find到的文件传入后面的指令中,通常不用|,因为不适配很多命令
 find /etc -name passwd | xargs ls -l   xargs:表示传递参数 传递到后面的命令中
 grep :文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,打印匹配到的行.
 find /path | xargs grep "string"      # 将find查找的所有文件 作为参数传递给 grep进行过滤字符串,也就是文字
 sudo find / -iname "*opencv*"w  :  find ~/bevlanedet/ -iname 'apollo*'   -i通常表示不区分大小写
 netstat -apn | grep client     查看客户端网络连接状态
 netstat -apn | grep port    查看端口的网络连接状态
 nc 127.1 9527 创建虚拟的IP+port,给网络编程的创建cs模型用的
 ps ajx: 查看后台进程
 ifconfig
 录屏 shift ctrl alt r
 .rviz配置参数 是从Alpha 到 value的
 查看rosbag坐标系: rostopic echo /velodyne_points | grep frame_id 要在rviz显示,各种class,也就是各种消息的frame_id要一致
 //获取参数服务器上(也就是launch中或yaml中)的参数,获取到参数的值后赋值给后面的参数,如果没有,就对后面的参数使用默认值,eg:
       private_nh.param("use_map", use_map, false);
       rosparam set    rosparam get 同上,即从参数服务器上get(赋给后面)或set(对该名字的参数值进行set)
       <remap from="~map"   to="/global_map"/>   重映射 话题、服务或参数名称  ~表示引用节点私有命名空间下的(也没啥)
       对应的,/global_map表示全局命名空间,话题通常加/,不加则表示相对于节点的私有命名空间,则话题变为:/node/global_map(rostopic list 可以看出差别)
 rosservice list:list; rosservice list -n :list(node); rosservice info service_name:information;
 rosparam list    
 rostopic type topic_name    rostopic list -v: list(node)
 pkill 用于杀死一个进程,与 kill 不同的是它会杀死指定名字的所有进程 : pkill -f system_real_robot.launch
 kill PID、kill -9 PID  根据id杀死进程,pkill更好用点
 全编译:catkin_make -DCATKIN_WHITELIST_PACKAGES=""  出现复制别人文件编译时有问题的情况,需要:删掉上锁的cmakelists文件,再catkin_init_workspace
 watch -d -n 0.1 nvidia-smi 观看gpu内存变化 -d表示对变化的进行高亮 、 -n 后为秒
 firefox -profilemanager 打开firefox 设置打开firefox的profile
 机器的 CPU 数量可通过命令  cat /proc/stat | grep cpu[0-9] -c    我的:16
 locate xxx.h
 pcl:gedit /usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfigVersion.cmake
 pkg-config opencv4 --libs 库地址
 pkg-config opencv4 --modversion 版本
torch.set_printoptions(threshold=np.inf)
 np.set_printoptions(threshold=np.inf)
    
     调用摄像头:直接    roslaunch usb_cam usb_cam-test.launch
     运行命令 sudo nautilus  就可以打开一个具有管理员权限的文件管理器,然后就可以在不切换到管理员的条件下拷贝文件
     tensorrt 安装到csdn收藏的tensorflow 处(tf还没有装)
     ikuuu.org ./clash -d .   chomd +x xxx chmod 777 xxx
     chmod +x xxx    ./clash -d .
     uname -a 查看电脑架构
     sudo su   cp/mv 源文件 目标文件  unzip/zip  filename.zip  dpkg -i/-p filename  find *.cpp find ???.cpp
     rosnode list rostopic info
     chmod 777 filename    ping          template<typename>T1  template<class T2,class t3>  实例化:Student<int,double>student1
     vim: i编辑   :wq! 保存并强制退出 Vim 编辑器      :q!  不保存,且强制退出 Vim 编辑器        u:撤回  ctrl_r反撤回 dd ndd删除 y nyy 复制 p P粘贴   i 编辑   x删除
     gcc: gcc -c filename 汇编   gcc filename.cpp -o hello ./hello  生成可执行
     }
     ffplay -autoexit w4.mp4
     ctrl alt - vscode代码导航后返回  crtl shift left, pycharm代码导航后返回
     返回进入此目录之前所在的目录 cd -
     c++ :        stoi: string型变量转换为int型变量   stol: string型变量转换为long型变量   stoul:string型变量转换为unsigned long型变量
             stoll: string型变量转换为long long型变量(常用)  stoull:string型变量转换为unsigned long long型变量 stof: string型变量转换为float           stod: string型变量转换为double型变量(常用)   stold:string型变量转换为long double型变量
     
 # deep-learning:
     pip list | grep torch
     kill -9 PID
     torch==1.8.0
     torchvision==0.9.0
     prime-select query 查看目前的显卡使用模式
     ls /usr/src | grep nvidia 查看已安装驱动版本信息
     conda install pytorch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 cudatoolkit=11.1 -c pytorch -c conda-forge
     pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113 加cu对应到版本(不加cu就不行,就会安装其他版本cuda 如10.2)
     conda install pytorch==1.12.1 torchvision==0.13.1 torchaudio==0.12.1 cudatoolkit=11.3 -c pytorch
     pip uninstall torch
     #创建名为your_env_name的环境
     conda create --name your_env_name
     #创建制定python版本的环境
     conda create --name your_env_name python=2.7
     conda create --name your_env_name python=3.6
     #创建包含某些包(如numpy,scipy)的环境
     conda create --name your_env_name numpy scipy
     #创建指定python版本下包含某些包的环境
     conda create --name your_env_name python=3.6 numpy scipy
     删除虚拟环境:
         conda remove -n your_env_name --all
         conda remove --name your_env_name --all
     #查看--安装--更新--删除包
     conda list:
     conda search package_name# 查询包
     conda install package_name
     conda install package_name=1.5.0
     conda update package_name
     conda remove package_name
     退出创建的虚拟环境
     source deactivate your_env_name
      #pycharm:
     tensorboard --bind_all --logdir=tensorboard/laneatt_r34_tusimple 用tensorboard显示loss曲线 注意是/  在ws下,后面是路径,因为tensorboard为2.3.0 所以加了--bind_all 才行
     tensorboard --logdir=logs --port=6007 输出再制定端口下
     
     {:04d}:保留4位整数,前面位补0。eg:34 - > 0034
     Ctrl+Shift+Backspace    导航到最近编辑区域
     import torch.cuda
     
     print(torch.cuda.is_available())
     print(torch.version.cuda)
     print(torch.__version__)
     print(torch.cuda.get_arch_list())
     import torch
     from torch.backends import cudnn
     print(cudnn.is_available())
     print(torch.backends.cudnn.version())  查看torch下的cudnn版本 这是在安装cudatoolkit时默认对应的版本
     print(torch.cuda.device_count())
     ls -l /usr/local | grep cuda 查看该目录下有哪些cuda版本 ->表示软连接  ,表示当前使用的是cuda-11.3版本。
     如果当前机器上安装了多个cuda版本,可以使用修改软链接的方式来修改系统使用的cuda版本,命令如下:sudo ln -snf/usr/local/cuda-8.0/usr/local/cuda(还是别用这个吧,还是在bashrc中修改) :这种应该cudnn不会变 还是用cuda中的   或者修改bashrc
     cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2 查看系统cuda的cudnn版本
     现存     cuda:11.3: cudnn:8.4.1
         cuda-11.3: cudnn:8.4.1      不敢乱改为8.2.0  
         cuda-11.7:cudnn:8.4.1    听说向下兼容, 是不是可以conda install pytorch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 cudatoolkit=11.1 -c pytorch -c conda-forge 试一试
                         好像是可以的
 换成pip:pip install torch==1.8.0+cu111 torchvision==0.9.0+cu111 torchaudio==0.8.0 -f https://download.pytorch.org/whl/torch_stable.html
#python:
     5-8:加载模型:
     1:torch.save(model, "xx/xx/xx.pth")    ->   torch.load("xx/xx/xxx.pth") (这是模型结构+模型参数,所以内存大)一般不这个
     2:torch.save(model.state_dict(), "xx/xx/xx.pth") (字典形式:模型参数) 推荐这个
                 ->   model = .get_model(实例化模型)
                      model.load_state_dict(torch.load("xx/xx/xx.pth"))          
     fp16是指采用2字节(16位)进行编码存储的一种数据类型;同理fp32是指采用4字节(32位);
     # son.load()从json文件中读取数据
         # json.loads()将str类型的数据转换为dict类型 json->pythonz
         # json.dumps()将dict类型的数据转成str python->json
         # json.dump()将数据以json的数据类型写入文件中
         # read()  所有的数据一次性读取出来, data的数据类型是一个字符串
         # readline() 读取的是一行内容, 然后是带换行符的, 所有会有空行, 后续会说明如何去掉换行符”\n”.
         # readlines() 读取的是一个列表, 注意换行符是包含在字符串的内容中
         action='store_true’:     default的优先级更高,有default就看default。即默认就为default,指定如python test.py --save_predictions 就相反为false
                     无default时:默认即false,指定python test.py --save_predictions即相反为true
         action='store_false’    默认值是True。需手动指定该参数,该参数才为False    (相反)    
         torch.bmm(input1, input2) 只能三维 对后两位作矩阵运算
         a[起点::步距] 当步距为负数时,则为倒叙。无起点时,则从start或end为起点(由正负判断) 三维b [..., 0] = b[:, :, 0] 表示 只要第0列的  b[..., 0, :] = b[:, 0] 表示只要第0行的
         Image.open或cv.imread(这个不确定)还有load等,好像是这样 :同级目录可以直接读取,非同级就要相对读取,即使它在ws下也要相对读取,或者使用绝对路径
         from和import都要从根开始 用.递进  from.XXX 即同级目录下  from.. 即上级目录下(最好使用绝对路径,即从ws开始from,不要用相对,问题多,相对是要在包里面才能这样写)  不要数字命名python文件 无法import  import要么同级、要么ws根目录的文件(from同级需要加.) 若是文件夹下 需要新建空的init文件 表示package
         import: 同级引用同级或ws下 ,相对有问题就换成ws下的路径(半绝对)
         figure, axes = plt.subplots(num_rows, num_cols, figsize=figsize)  创建多个子图
         train_loss_sum += loss.cpu().item() 得到一个batch的loss的和
         不要同名复制 如(loss = loss(y_hat, y), loss.backward()) 容易出事
         %d:int, %s:char, %.几f:float,保留几位小数
         blockneck 瓶颈结构  __getitem__ :p[k]
         fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'))
         plt.rcParams['figure.figsize'] = figsize
         plt.Rectangle
         figure, axes = plt.subplots(num_rows, num_cols, figsize=figsize)
             output_features = list(map(id, pretrain_net.fc.parameters()))
         feature_params = filter(lambda p: id(p) not in output_features, pretrain_net.parameters()), id(p) not in output_features这个就是返回的
         optimizer = optim.SGD([
             {'params':feature_params},
             {'params': pretrain_net.fc.parameters(), 'lr': 0.1}
         ], lr=0.01, weight_decay=0.001)                                    
         array = np.array(pairs)
         base_anchors = np.stack([-ssw, -ssh, ssw, ssh], axis=1) / 2  # 列上拼接 、自动转换,    rehsape、unsqueeze(错位相加、相乘)
         shift_x, shift_y = np.meshgrid(shifts_x, shifts_y)  # 生成图布内所有坐标点 分别得到x、y坐标
     unsqueeze: 重要性,在对应相加相乘时,同即可,在错位相加相乘时,需不同     有返回 需要 = 接收 并且广播机制也是因为他,因为对+一,一已经降维,需要unsqueeze
     torch.full  创建一个大小,值全为fill_value的张量。张量的dtype是从fill_value(可以是bool)推断出来.
     torch.nonzero 返回非0的idx  torch.nonzero(max_ious >= iou_threshold)
     np.concatenate = torch.cat
     uniques, counts = combined.unique(return_counts=True)     non_keep = uniques[counts==1]
     class_id[non_keep] = -1   class_id = class_id[all_id_sorted]
     !!! torch.cat((x1, x2), dim=1), 一般dim=几,表示维度上的dim会进行变换或消失,如torch.max(a, dim=1)
     
     iter(train_iter).next()  iter列表迭代器 用next得到列表迭代其的第一个等
         print(len(bbox.shape))
         reduction='none':会输出一个形状为 (batch_size, num_classes) 的矩阵,表示每个样本的每个类别的损失
         reduction='sum' 时,函数会对矩阵求和,输出一个标量,表示所有样本的损失之和
         reduction='mean' 时,函数会对矩阵求平均,输出一个标量,表示一个batch中样本的平均损失
         mae:平均绝对误差
         l.mean().backward()  # 一个batch的平均损失 反响传播只能以标量的隐式创建 所以有的需要mean
         用Image 和 imread读到的图片数值在0-255之间 送入网络‘通常’需要归一化处理:/255 -> np.array(img) (Image时) -> 然后转为tensor:torch.from_numpy(img), 如果只是show则都不用
         空洞卷积 : dilation
         nn.embedding: (num_embedding:输出个数, dim:维度) 该层只有一个参数 : .weight: 已标准化的参数 ,输入为离散的num_embedding(torch.arrange(num_embedding),输出得到还是原大小(num_embedding:输出个数, dim:维度),这也就是不同于linear的地方,linear:为输入为num_embedding个向量
         zip([256] + [256] * 2, [256] * 2 + [4]); [1].append([2]),[1, [2]], 而[1] += [2],为[1, 2]
         y / (y[:, -1:, :])   运算(+ - * /)维度个数要相同  y[:, -1:, :]:三维   y[:, -1, :] 两维   y[:, -1:, :]其中-1:非常讲究 有冒号:则维度没有下降 -1:则其为1行 ,如果-2:, 2:, :2都不止为1
          nn.conTranspose2d(in,out,k,p,s) :参数填写原来卷积con2d的参数即可(这句话错误,应根据后面这句话),如果不知道,需要自己计算:k=2p+s, (原x-k+2p)/s + 1 =现x
          指定卷积核的权重(应该不算指定输出形状):conv.load_state_dict({'weight': K}) 其中conv = nn.Conv2d(in, out, k, bias=False) 则相应k应为:(out, in, k, k)
          仅仅copy值:conv_trans.weight.data.copy_(bilinear) 不决定形状
          math.ceil() 向上取整  round() 四舍五入
          logger = logging.getLogger(__name__)   logger.info() 输出是在logger  创建用logging.basicConfig logging.FileHandler  .setLevel  .setFormatter
          x.repeat(2, 3, 4) 0维复制2两次 1维复制3次 2维复制4次(对应复制, 多余则往前不往后)   x.repeat_interleave(3, 0) 将0维复制三次:[c, d] -> [c, c, d, d]
          1. 均匀分布 torch.nn.init.uniform_(tensor, a=0, b=1) 2. 正太分布torch.nn.init.normal_(tensor, mean=0, std=1) 3. 初始化为常数torch.nn.init.constant_(tensor, val) 4 预防一些参数过大或过小的情况,再保证输入输出的weight方差一样的情况下进行缩放,便于计算torch.nn.init.xavier_uniform_(tensor, gain=1.0)
          FCN FPN FFN   reg-loss 用的nn.smothloss :平滑loss:L1和L2 loss的结合
          print(priors[:, 3].shape) :[192], print(priors[:, 2:3].shape :[192, 1], 这样是会保留多一个维度的
          MACs模型复杂度(会根据输入变化),Params模型参数量(模型的固定量) code :/hfome/dai/LaneATT_lib_/unet_522.py 里面
          装网络时,要self.net = nn.ModuleList()或者self.net = nn.Sequential(),不能用self.net = [] 来装
          torch.gather(a=[[1, 2], [3, 4]], 0, b=[[0, 0], [1, 0]]),因为为0,所以后面b的数字表示行数,列数则由自身位置表示,即[0][0] = [0][0] =1,[1][0] = [1][0] = 3
          np.where(inputs > thre):以array的形式返回n组坐标,每组代表一个维度,类似于meshgrid的返回
          x = F.conv2d(x, weight=w, bias=b, stride=1, padding=0, groups=3)
          is_cuda, x = x.to(torch.devide('cuda')) 要有返回接收才行,关于x.cuda还没有弄清楚,网络因为继承nn可以to(device), 创建的一般用device=device
          去除tensor指定行列:a = a[:, torch.arange(a.size(1)) != 3]
      dict 的 update方法:类似于list的extend方法,即尾接dict的元素    
          id = [5]   list(map(student, id)),相当于把id的所含参数传入student这个类,进行实例化,但id要以list的方式传入
          在tensor中取元素或tuple: 取元素:a[-2].item(), 取元素做tuple或list:a.tolist()[-2:]
          assert expression, 'message ',一般是assert一个表达式,如assert a==b,用来判断表达式
          assert len(kwargs) == 4, '参数必须是4个'
          if 'name' not in kwargs:
             raise ArgsError('缺少姓名参数')   raise 则用来抛出指定异常
          try-exception,表示try能走通不报错,就走,否则就会走exception的报错
          try:
         num1 = int(input("请输入被除数:"))
         num2 = int(input("请输入除数:"))
         result = num1 / num2
     except ZeroDivisionError:
         print("除数不能为0,请重新输入!")  总结:三者差距不大 特别是后两者,都用来抛出指定异常
          math.isclose(a, b)、np.allclose(a, b) 判断a、b是不是几乎相等
          with open('filename', 'r') as f:  r:读文件 w:重写文本文件 wb:重写二进制文件 a:追加写文本文件
          nn.Conv2d:类 接口,实例化和前向,F.conv2d(x...),函数接口,直接传入输入,得到输出,一般大写为类接口,小写为函数接口
          x.numel() 、torch.numel(a) a的元素个数  元素数量
          exit() 放在执行部分,可以不执行后续,类似于断点
          仅当p为tensor或array时,可以p>0,从而输出T、F, list则不行
          print(f'y = {y}')        print('y = {}'.format(y))   输出的方式 试着用前者 相比于print('y', y) 更加直观
          @ :当@连接的两项为矩阵时:m×n)维×(n×y)维 =(m×y)维;  @连接的两项一项为矩阵,一项为数组时(m×n)维×(1×n)维 =(1×m)维
clrnet:
     使用指定的GPU及GPU显存 os.environ["CUDA_VISIBLE_DEVICES"]
     ‘,’.join()以指定的字符(分隔符)连接生成一个新的字符  
     @property 将方法变成属性调用,调用时不加括号,并且它的属性类似私有属性,无法进行赋值,由构造函数就定好  def __repr__(self)当直接打印类的实例化对象时,系统将会自动调用该方法,输出对象的自我描述信息,用来告诉外界对象具有的状态信息 def __str__(self),好像和repr类似
     @staticmethod:可以在不实例化的情况下从类中调用该方法,没有self参数,且无法用任何init的参数,就跟一个扎根在类中的外部函数一样。
     @classmethod:可以在不实例化的情况下从类中调用该方法,没有self参数,但需要一个‘cls’参数,且可以用类的属性,方法,可以用init的参数
     eval :接收运行一个字符串表达式,返回表达式的结果值。一定是字符串 一定是表达式 因为eval本身没啥用 就是output一下
     .pop 删除并返回字典或列表的一个元素 字典就返回指定key的value
     inspect.isclass bool
     构造的函数里的self. 也为构造的东西
     一种采样方法, 类似放射变换:grid_sample((16, 64, 10, 25), (16, 192, 32, 2(必须为2)), align_corners=True)  -> [16, 64, 192, 32]  输出其值来自于:输入input的(x,y)中 的四邻域插值得到的
     *和**分别是用于tuple和dict的,都有两个场景,分别是作为打包参数和解包参数使用(详细csdn自己艘),就是拿出tuple的值和dic的value进行传入或取出
     torch.set_printoptions(threshold=np.inf)  打印tensor防止省略,打印完整
     img在dataloder时,经过totensor会自动走归一化的操作,即数据大小在0-1之间
     
     import torchvision.transforms as t
     1:归一化在totensor后面,2:如果用cv2读图片,要用transform就要先用ToPILImage转成pil的 3:如果Normalize了,可视化时你是无法恢复原来的样子的
     trans_image = t.Compose([
         t.ToPILImage(),
         t.Resize((input_shape[0], input_shape[1])),
         t.ToTensor(),
         t.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))])
     
     trans = trans_image(img)
     
     转回去: ,因为ToTensor最自动除255归一,所以要* 255(好像不一定,要自己试),且要uint8无符号
     trans = (trans * 255).permute(1, 2, 0)
     trans = (trans.cpu().numpy()).astype('uint8')
     trans1 = cv2.resize(trans, (1920, 1080))    # 会变糊
     cv2.imshow('11', trans)
     cv2.waitKey(5000)
     
     canvas = np.expand_dims(canvas, axis=0).repeat(3, axis=0) 这个np的等价于 torch的expand
     
     torch.set_printoptions(threshold=numpy.inf)  设置 将 tensor 完全显示 不省略
     ( 3, 144, 256) 和 (3) 相乘  result = tensor1 * tensor2[:, None, None] :是通道对应相乘,   tensor1 * tensor2[None, None, :]  :列维度对应相乘
     a.size = [4,5,3] b.size = [4,5]  a[b] = c c为[3]  :  mask = img[0] == i  img[mask] = [255, 0, 0]
     
         
         
     
     
     
 deploy:
     onnx:
         /home/dai/pytorch_deeplearining/code/moxingbushu_1.py  (用图片等进行测试模型详见文件中, 算子转换详见4, 裁减onnx模型详见5)
         netron(可视化onnx模型):https://netron.app/   pip install netron  netron xxx.onnx
         onnx转换和推理测试的工具trtexec 不明白如果一个指令就可以,为什么还要写这么多代码呢
         trtexec --onnx=static.onnx --saveEngine=static.engine
         trtexec --loadEngine=static.engine 测试推理
         trtexec --loadEngine=static.engine --duration=1000  持续
         trtexec --onnx=dynamic.onnx --minShapes=x:1x1x3x3 --optShapes=x:50x1x3x3 --maxShapes=x:100x1x3x3 动态batch
         trtexec --loadEngine=dynamic.engine --shapes=x:100x1x3x3 测试推理
         # 这里相当于要给一组输入,这个输入x的大小要和我们的输入大小要一致 让模型跑起来, 这也就解释了为什么要配对的原因
         model = MODEL()
         state_dict = torch.load('srcnn.pth')['state_dict']
         model.load_state_dict(state_dict)
         dynamic_axes={"input.0": {0:"batch"}, "input.1": {0:"batch"}, "output.0": {0:"batch"}}
         torch.onnx.export(model, x, "srcnn.onnx", opset_version=11, # ONNX 算子集的版本
                 input_names=['input'], output_names=['output'],
                 dynamic_axes={'input': {0: 'batch0', 2: 'batch2', 3: 'batch3'},
                 "input.0": {0:"batch"}, "input.1": {0:"batch"}, "output.0": {0:"batch"},# 动态size的位置,关系输入着x要不要固定 但是一般只指定batch为动态
             'output': {0: 'batch00', 2: 'batch22', 3: 'batch33'}})    
         export后跟一句用来保存尺寸变化用来可视化:onnx.save(onnx.shape_inference.infer_shapes(onnx.load("model.onnx")), "model.onnx")
         ort_session = onnxruntime.InferenceSession("srcnn.onnx")  # 用onnxruntime推理引擎测试 onnx模型
         ort_output = ort_session.run(['output'], {'input': input_img})[0] # 后者为字典,且有‘input’,对因之前
         
         onnx(不同于torch.onnx)的model有gragh计算图,计算图graph有node、input, output 等,之前torch.onnx.export(['input'], ['output']),这两个名称是对应后面的读取的
     
     
     
     
 problem:
     'builtin_function_or_method' object has no attribute 可能没给方法加括号
     pycharm报错:无法下标:看看是不是size和shape的问题 需要换着使用size
     关于pycharm一直indexing导致卡: File->Setting->Project->Project Structure->Exclude  一些文件夹 如dataset
     pycharm run出现Empty suite: py文件不要用test为首进行命名。
     RuntimeError: CUDA error: no kernel image is available for execution on the device:这是torch的cuda版本和nvcc的不对应,太低了,比如我的就不支持10的cudatoolkit
     若出现model = model.to(device) 这一步卡吨的,可以换成pip进行安装的torch和cudatoolkit
     绝对路径出现问题:
         from lanenet_model import lanenet
         ModuleNotFoundError: No module named 'lanenet_model'
         在代码中加上:    import sys
                 sys.path.append('/home/dai/lanenet-lane-detection-master/')
     踩坑problem:测试时model.eval的效果没有model.train的效果好,或者说model.eval完全就没有效果了
         原因:可能是训练反复设置model.eval、model.train,batch太小等的原因