画流程图
流程图软件正常可以选用微软的 visio,但是我喜欢小巧的软件,然后再网上找了以下,找到一个合适的,既有在线版也有桌面版的。 drawio,这个软件在线版地址:https://www.draw.io 桌面版地址:https://github.com/jgraph/drawio-desktop
流程图软件正常可以选用微软的 visio,但是我喜欢小巧的软件,然后再网上找了以下,找到一个合适的,既有在线版也有桌面版的。 drawio,这个软件在线版地址:https://www.draw.io 桌面版地址:https://github.com/jgraph/drawio-desktop
pip 安装包的时候,经常会碰到下载源码包速度太慢,反复重启的问题。有时候,挂代理效果也不明显。 这个时候,可以在一台电脑上把需要的包下载好,然后复制到目标电脑上,本地安装,这样就不会有太慢的问题了。 具体方法如下:
pip download xyz
,这样就把 xyz 这个包需要的包括依赖全部下载下来。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
在算法中运用迭代器时,很可能会用到其相应型别,什么是相应型别?迭代器所指之物的型别便是其中之一。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;
};
本篇适合不熟悉这两个函数的读者
以前在使用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>
pytorch 中的 softmax 函数功能和具体的 c++ 实现如下:
.gitconfig 位于 C:\Users\Administrator
下
.ssh 也位于 C:\Users\Administrator
下
类似于 python 的 numpy 库的 c++ 实现 xtensor 学习记录。
安装 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
最近需要把一些 python 版本的程序转为 c++ 的程序。 python 中使用了很多 numpy 的调用,于是就再找 c++ 的实现。 找了一圈下来,发现最适合的可能就是 xtensor。 github: https://github.com/xtensor-stack/xtensor 使用: https://xtensor.readthedocs.io/en/latest/numpy.html
The GNU Scientific Library is a GPL software written in C. Thus, it has a C-like allocation and way of programming (pointers, etc.). With the GSLwrap, you can have a C++ way of programming, while still using the GSL. GSL has a BLAS implementation, but you can use ATLAS instead of the default CBLAS, if you want even more performances.
The boost/uBLAS library is a BSL library, written in C++ and distributed as a boost package. It is a C++-way of implementing the BLAS standard. uBLAS comes with a few linear algebra functions, and there is an experimental binding to ATLAS.
eigen is a linear algebra library written in C++, distributed under the MPL2 license (starting from version 3.1.1) or LGPL3/GPL2 (older versions). It's a C++ way of programming, but more integrated than the two others (more algorithms and data structures are available). Eigen claim to be faster than the BLAS implementations above, while not following the de-facto standard BLAS API. Eigen does not seem to put a lot of effort on parallel implementation.
Armadillo is LGPL3 library for C++. It has binding for LAPACK (the library used by numpy). It uses recursive templates and template meta-programming, which is a good point (I don't know if other libraries are doing it also?).
xtensor is a C++ library that is BSD licensed. It offers A C++ API very similar to that of NumPy. See https://xtensor.readthedocs.io/en/latest/numpy.html for a cheat sheet.
参考: https://stackoverflow.com/questions/11169418/numpy-style-arrays-for-c https://github.com/dpilger26/NumCpp
torch.Tensor
生成一个 tensor 类型。>>> import torch
>>> x=torch.Tensor([[1,2,3],[4,5,6]])
>>> x
tensor([[1., 2., 3.],
[4., 5., 6.]])
参考: https://www.jianshu.com/p/314b6cfce1c3 https://pytorch-cn.readthedocs.io/zh/latest/package_references/Tensor/ https://blog.csdn.net/weixin_42018112/article/details/91383574
torch.nn.functional.softmax(input, dim=None, _stacklevel=3, dtype=None)
用于对设置的维度上的数进行收缩,让他的和为 1.>>> import torch
>>> from torch import nn as nn
>>> input = torch.randn(2, 3, 4)
>>> input
tensor([[[-0.1335, 0.1574, -0.4618, -0.1629],
[-1.1302, -0.2782, 0.2689, 1.4722],
[ 1.8547, 3.0593, 1.7146, -0.4395]],
[[-0.0102, 1.4679, 0.0138, 0.5245],
[ 2.2345, 2.0089, 2.0074, 0.4197],
[-1.4187, -0.0887, 0.9257, 0.2516]]])
>>> torch.nn.functional.softmax(input)
tensor([[[0.4692, 0.2124, 0.3833, 0.3346],
[0.0334, 0.0922, 0.1495, 0.7413],
[0.9635, 0.9588, 0.6876, 0.3338]],
[[0.5308, 0.7876, 0.6167, 0.6654],
[0.9666, 0.9078, 0.8505, 0.2587],
[0.0365, 0.0412, 0.3124, 0.6662]]])
>>>
>>> torch.nn.functional.softmax(input, dim=0)
tensor([[[0.4692, 0.2124, 0.3833, 0.3346],
[0.0334, 0.0922, 0.1495, 0.7413],
[0.9635, 0.9588, 0.6876, 0.3338]],
[[0.5308, 0.7876, 0.6167, 0.6654],
[0.9666, 0.9078, 0.8505, 0.2587],
[0.0365, 0.0412, 0.3124, 0.6662]]])
>>> torch.nn.functional.softmax(input, dim=1)
tensor([[[0.1153, 0.0504, 0.0841, 0.1452],
[0.0426, 0.0326, 0.1746, 0.7447],
[0.8421, 0.9171, 0.7413, 0.1101]],
[[0.0936, 0.3415, 0.0923, 0.3757],
[0.8835, 0.5866, 0.6779, 0.3383],
[0.0229, 0.0720, 0.2298, 0.2860]]])
>>> torch.nn.functional.softmax(input, dim=2)
tensor([[[0.2482, 0.3320, 0.1788, 0.2410],
[0.0479, 0.1122, 0.1939, 0.6460],
[0.1885, 0.6287, 0.1638, 0.0190]],
[[0.1232, 0.5403, 0.1262, 0.2103],
[0.3626, 0.2894, 0.2889, 0.0591],
[0.0487, 0.1843, 0.5081, 0.2589]]])
默认是对于第一维进行伸缩。 dim = 0, 0.4692 + 0.5308 = 1 dim = 1, 0.1153 + 0.0426 + 0.8421 = 1 dim = 2, 0.2482 + 0.3320 + 0.1788 + 0.2410 = 1
参考: https://blog.csdn.net/m0_46653437/article/details/111610571 https://pytorch.org/docs/master/nn.functional.html#torch.nn.functional.softmax https://blog.csdn.net/chengyq116/article/details/106893773
torch.clamp(input, min, max, *, out=None) → Tensor
用于限制数值的上限和下限,把所有数据限制在设定好的上下限之间。>>> a = torch.randn(4)
>>> a
tensor([-1.7120, 0.1734, -0.0478, -0.0922])
>>> torch.clamp(a, min=-0.5, max=0.5)
tensor([-0.5000, 0.1734, -0.0478, -0.0922])
参考: https://pytorch.org/docs/stable/generated/torch.clamp.html