2021年4月

pip 安装包的时候,经常会碰到下载源码包速度太慢,反复重启的问题。有时候,挂代理效果也不明显。 这个时候,可以在一台电脑上把需要的包下载好,然后复制到目标电脑上,本地安装,这样就不会有太慢的问题了。 具体方法如下:

  1. 准备一台可以科学上网的电脑,选择 http 代理,全局。
  2. 在科学上网的电脑上,安装和目标机器相同版本的 python。
  3. 新建空目录,在目录路径打开命令行,pip download xyz,这样就把 xyz 这个包需要的包括依赖全部下载下来。
  4. 复制这个目录到目标机器。
  5. pip install --no-index --find-links=. xyz 这个是从本目录开始安装 xyz 的包。

如果碰到需要一次安装多个的,可以使用 requirements.txt

参考: https://www.pythonf.cn/read/20932 https://stackoverflow.com/questions/11091623/how-to-install-packages-offline https://blog.csdn.net/wangyaninglm/article/details/54177720 https://zhuanlan.zhihu.com/p/70065906

转自: https://blog.csdn.net/GUI1259802368/article/details/72737331?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

在算法中运用迭代器时,很可能会用到其相应型别,什么是相应型别?迭代器所指之物的型别便是其中之一。C++ 有函数模版推导机制,例如:

template<class I ,class T>
void  func_imp1(I iter, T t)
{
       T tmp;      // 这里解决了问题,T就是迭代器所指之物的型别,本例为int
};
template <class I>
inline  void func(I  iter)
{
       func_imp1(iter ,*iter);        // func 的工作全部移往 func_imp1
}
int main()
{
      int i;
      func(&i);
}

迭代器所指对象的型别。成为该迭代器的 value type。上述的参数型别推导虽然可用于value_type,但是当value type 必须用于函数的传回值,就束手无策了,毕竟函数的 “template 参数推导机制” 推而导之的只是参数,无法推导函数的返回值型别。

其他方法如声明内嵌型别似乎是个好主意,例如:

template<class T>
struct MyIter{
     typedef  T  value_type;   // 内嵌型别声明
     T* ptr;
     MyIter (T*  p=0): ptr(p){ }
     T& operator*() const {return  *ptr;}
      //....
};
template<class I>
typename I:: value_type
func(I ite)
{  return *ite;  }
//...
MyIter<int>ite(new  int(8));
cout<<func(ite);

注意:并不是所有的迭代器都是 class type。原生指针就不是!如果不是 class type,就无法为它定义内嵌型别。但是STL绝对必须接受原生指针作为一种迭代器,因此需要一种方法将上述的一般化概念针对特定情况做特殊化处理。

偏特化就可以做到,如下面一个class template:

template<typename T>
class  C {  ...  };          //这个泛化版本允许T为任何型别
很容易接受它有一个形式如下的 partial specialization:
template<typename T>
class C<T*>{  ...  };     //这个特化版本仅适用于“T为原生指针”的情况
                                   // “T为原生指针” 便是 “T为任何型别” 的一个更进一步的条件限制

下面这个 class template 专门用来 “萃取”迭代器的特性,而 value type正是迭代器的特性之一:

template<class I>
struct  iterator_traits{
    typedef  typename I::value_type     value_type;
};

这个所谓的 traits,其意义是,如果 I 定义有自己的 value_type,那么通过这个 traits 的作用,萃取出来的 value_type 就是 I:: value_type.换句换说,如果I定义有自己的 value type,先前那个 func() 可以改写成这样:

template<class I>
typename iterator_traits<I>::value_type
func(I  ite)
{ return  *ite; }

但是除了多一层间接性,又带来什么好处呢?好处是 traits 可以拥有特化版本。现在,我们令 iterator_traits 拥有一个 partial specializations 如下:

template<class  T>
struct  iterator_traits<T*>{           //偏特化版本------迭代器是个原生指针
    typedef   T  value_type;
};

最常用到的迭代器的相应型别有五种:value type,difference type,pointer,reference,iterator,iterator catagoly。如果你希望你所开发的容器能与STL水乳交融,一定要为你的容器的迭代器定义这五种相应型别。特性萃取机 traits 会很忠实的提取出来:

template<class  I>
struct  iterator_traits{
   typedef  typename  I:: iterator_category     iterator_category;
   typedef  typename  I:: value_type               value_type;
   typedef  typename  I:: difference_type       difference_type;
   typedef  typename  I:: pointer                     pointer;
   typedef  typename  I:: reference                 reference;
}; 

转自: https://blog.csdn.net/simahao/article/details/405455?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

本篇适合不熟悉这两个函数的读者

以前在使用stl的过程中发现bind1st和bind2nd这两个函数,当时不太理解什么意思,今天在网上查了一下相关资料发现竟然很简单,下面我就具体解释一下他们的用法。

bind1st和bind2nd函数用于将一个二元算子(binary functor,bf)转换成一元算子(unary functor,uf)。为了达到这个目的,它们需要两个参数:要转换的bf和一个值(v)。

可能这么解释以后大家还不是很清楚,那么就说点白话吧。我们在做比较的时候所写的表达式像 x > k ,x < k,这里的k是一个参数表示你程序里面的表达式要和k值去比较。上面这两个表达式对应的应该是bind2nd ,简单的理解就是把k作为比较表达式的第二个参数。如果使用bind1st则对应的表达式是 k > x,k < x,也就是把k作为比较表达式的第一个参数。大家可能会注意到这里面没有=的比较,先别着急,后面将会说道如何实现=的比较。先举两个例子看看bind1st和bind2nd的用法。

int a[] = {1, 2, 100, 200};

std::vector< int> arr(a, a + 4);

// 移除所有小于100的元素
arr.erase( std::remove_if( arr.begin(),  arr.end(),
    std::bind2nd( std::less< int>(), 100)), arr.end());

这里的比较表达式相当于arr.value < 100

如果用bind1st则表达的意思就恰恰相反

// 移除所有大于100的元素
arr.erase( std::remove_if( arr.begin(),  arr.end(),
    std::bind1st( std::less< int>(), 100)), arr.end());

这里的表达式相当于100 < arr.value

当然为了实现删除大于100的元素你同样可以使用bind2nd

// 移除所有大于100的元素
arr.erase( std::remove_if( arr.begin(),  arr.end(),
    std::bind2nd( std::greater< int>(), 100)), arr.end());

前面说道=的比较,比如说x <= k怎么实现呢,std又提供了一个好东西not1,我们可以说 !(x > k) 和 x <= k是等价的,那么我们看看下面的表达式:

// 移除所有小于等于100的元素
arr.erase( std::remove_if( arr.begin(),  arr.end(),
    std::not1(std::bind2nd( std::greater< int>(), 100))), arr.end());

说明:not1是否定返回值是单目的函数,std中还有not2它是否定返回值是双目的函数

例子需要包含头文件

#include <vector>
#include <algorithm>
#include <functional>

安装

安装 xtensor 之前需要先安装依赖 xtl, https://github.com/xtensor-stack/xtl https://github.com/xtensor-stack/xtensor

进入 xtl 源码目录运行命令:

cmake -DCMAKE_INSTALL_PREFIX=/usr
sudo make install

进入 xtensor 源码目录运行命令:

cmake -DCMAKE_INSTALL_PREFIX=/usr
sudo make install

简单使用

工程目录下创建 compile.sh

#!/bin/bash 

mkdir -p build
pushd build
cmake ..
make
make install
popd

相应的 CMakeLists 文件中添加:

set(CMAKE_CXX_STANDARD 14)

如果工程还涉及到 opencv,那么需要添加

    find_package(OpenCV REQUIRED)
    include_directories(${OpenCV_INCLUDE_DIRS})
    link_directories(${OpenCV_LIBRARY_DIRS})

    target_link_libraries(${name} ${OpenCV_LIBS})

如果工程中用到 cjsonobject,需要添加

    include_directories("${PROJECT_SOURCE_DIR}/CJsonObject")

如果工程运行的时候,需要某些库文件,那么可以新建一个 run.sh,里面可以如下添加库,然后运行:

#!/bin/bash

export LD_LIBRARY_PATH=./tengine/linux-arm64-v8a/lib/

./build/install/bin/classification