Quantcast
Channel: Sam的技术Blog
Viewing all 158 articles
Browse latest View live

Tensorflow基础学习五杂项

$
0
0
作者: Sam (甄峰)   sam_code@hotmail.com


x_data_2 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]
sp = tf.split(x_data_2, 2, axis=0)

with tf.Session() as sess:
    for c in sp:
        print("split:",sess.run(c))



split: [[1 2 3]
 [4 5 6]
 [7 8 9]]
split: [[10 11 12]
 [13 14 15]
 [16 17 18]]









x_data_2 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]
sp = tf.split(x_data_2, [1,2], axis=1)

with tf.Session() as sess:
    for c in sp:
        print("split:",sess.run(c))




split: [[ 1]
 [ 4]
 [ 7]
 [10]
 [13]
 [16]]
split: [[ 2  3]
 [ 5  6]
 [ 8  9]
 [11 12]
 [14 15]
 [17 18]]





常见的用法:

例如:有数据为NHWC--[batch, height, width, channels]

如果想把各个chanels的数据单独拿出来,则可以使用tf.split()

 

Tensorflow基础学习TFRecord-DataSet学习

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

0. 缘由:
对深度学习而言,因为训练数据通常极为庞大,所以在提高运算能力的同时,更高效的数据I/O操作也非常重要。

使用Tensorflow训练模型时,有三种数据加载方式:
A. 使用python 代码准备数据。
B. 预先加载数据,将需要训练的数据以变量形式保存于内存。
C. 利用管道从文件中读取。

当数据较小时,可以用python 代码进行batch, shuffle, padding等numpy类型的数据处理。 用placeholder+feed_dict 来将其导入到graph中变成Tensor类型数据。

但当数据数量远超内存大小时,就只能放到硬盘中,边用边读。 这就必须考虑数据的移动,读取,处理等速度了。Tensorflow推荐使用自带的TFRecords文件,可以提高速度,节省空间。

TFRecords文件以二进制进行存储,适合以串行方式读取大批量数据。

Training时,可以编写程序将普通的训练数据保存为TFRecords数据格式。


1. TFRecords文件的创建和写入:
TFRecords是以字典(dict)方式保存feature. 字典的每条记录保存一个特征(feature). 把所有特征存入字典。 
字典的Key记录feature的名字。 字典的value则记录feature的内容。



1.1: Feature值存储类型
Feature的值,必须是Tensorflow指定的feature类型中的一个:
int64, float32. string.
可以用以下方式构建feature值。
tf.train.Feature(int64_list=tf.train.Int64List(value= input))
tf.train.Feature(float_list = tf.train.FloatList(value=input))
tf.train.Feature(bytes_list=tf.train.BytesList(value=input))
注意: value传入的参数,必须都是list.

Tensorflow的Feature只接受List数据, 如果特征数据类型为矩阵或者Image.该如何处理呢?

处理方式有2:
A. 转为List类型。 将张量fatten成List.
B. 转为string类型。 使用  .tostring()转为string类型。

但不管使用何种方式,都会丢失shape信息。
可以该样本写入字典时,加入一个新的feature. 它的值就是转换数据的shape. 方便使用数据时转回。

1.2: TFRecords文件的创建思路
将一个样本数据的每一项特征组合成一个字典。 将样本数据组装成一个Example对象。
这个对象遵循protocol buffer协议。 将example对象序列化为字符串。
最终使用tf.python_io.TFRecordWrite()写入tfrecords文件。

例:
import numpy as np
import tensorflow as tf
from matplotlib import pyplot as plt
import matplotlib.image as mpimg

# 精度3位
np.set_printoptions(precision=3)
# 用于显示数据
def display(alist, show = True): 
    print('type:%s \nshape: %s' %(alist[0].dtype,alist[0].shape)) 
    if show: 
        for i in range(3): 
            print('样本%d is: %s' %(i,alist[i]))
scalars = np.array([1,2,3],dtype=np.int64)
print('\n标量:')
display(scalars)

vectors = np.array([[0.1,0.1,0.1], [0.2,0.2,0.2], [0.3,0.3,0.3]], dtype=np.float32)
print('\n向量:')
display(vectors)
matrices = np.array([np.array((vectors[0],vectors[0])), np.array((vectors[1],vectors[1])), np.array((vectors[2],vectors[2]))],dtype=np.float32)
print('\n矩阵:')
display(matrices)



# shape of image:(h,w,3)
img=mpimg.imread('1.jpg') 

tensors = np.array([img,img,img])
# show image
print('\n张量:')
display(tensors, show = False)
plt.imshow(img)


# open TFRecord file
writer = tf.python_io.TFRecordWriter('%s.tfrecord' %'test')

# we are going to write 3 examples,each example has 4 features:scalar, vector, matrix, tensor
for i in range(3):
    # create dictionary 
    features={}
    # write scalar ,type Int64,"value=[scalars[i]]" makes it to list
    features['scalar'] = tf.train.Feature(int64_list=tf.train.Int64List(value=[scalars[i]]))
    
    # write vector,type float,it is list,so "value=vectors[i]"
    features['vector'] = tf.train.Feature(float_list = tf.train.FloatList(value=vectors[i]))
    
    # write matrix,type float,but its rank =2,tf.train.FloatList only takes list, so we can flatten it to list
    features['matrix'] = tf.train.Feature(float_list = tf.train.FloatList(value=matrices[i].reshape(-1)))
    # however the shape info will disappear. we can save shape as vector here
    features['matrix_shape'] = tf.train.Feature(int64_list = tf.train.Int64List(value=matrices[i].shape))
    
    # write tensor,type float,rank =3,another way is to convert it to string
    features['tensor']         = tf.train.Feature(bytes_list=tf.train.BytesList(value=[tensors[i].tostring()]))
    # save shape 
    features['tensor_shape'] = tf.train.Feature(int64_list = tf.train.Int64List(value=tensors[i].shape))
  
    # feed dictionary to tf.train.Features
    tf_features = tf.train.Features(feature= features)
    # get an example
    tf_example = tf.train.Example(features = tf_features)
    # serialize the example
    tf_serialized = tf_example.SerializeToString()
    # write
    writer.write(tf_serialized)
# close  
writer.close()




说明:
A.  tf.train.Feature()
构建一个feature值。feature可接受int64, float32,string. 

features['scalar'] = tf.train.Feature(int64_list=tf.train.Int64List(value=[scalars[i]]))
给features这个字典添加一项,key为scalar. 
value为:int64类型。  因为scalers[i]是个标量,而value只接受List. 所以加了方括号,变成list.

features['vector'] = tf.train.Feature(float_list = tf.train.FloatList(value=vectors[i]))
给features这个字典添加一项,key为vector.
value为:float. 因为vectors[i]本来就是list.所以此处不加[].


features['matrix'] = tf.train.Feature(float_list = tf.train.FloatList(value=matrices[i].reshape(-1)))
features['matrix_shape'] = tf.train.Feature(int64_list = tf.train.Int64List(value=matrices[i].shape))
这里希望加一个特征,但这个特征是矩阵。所以需要转为List.
这里利用reshape(-1)把数据fatten为List. 则需要再加入一项,存取其shape.
matrices[i].shape也是个List.所以不加[].


    features['tensor']         = tf.train.Feature(bytes_list=tf.train.BytesList(value=[tensors[i].tostring()]))
    features['tensor_shape'] = tf.train.Feature(int64_list = tf.train.Int64List(value=tensors[i].shape))
另一种转换,并添加shape.

B. tf_features = tf.train.Features(feature= features)
用存好特征的字典生成一个tf.train.Features.

C. 生成样本。
tf_example = tf.train.Example(features = tf_features)
把features生成样本。

D:序列化样本:
tf_serialized = tf_example.SerializeToString()

E: 写入样本:
writer.write(tf_serialized)

所以此时,TFRecords文件中存入了3个Example.



2. Dataset的使用:
Dataset(tf.data.Dataset) 相当于一个数据集object.
这个Dataset,可以直接从list导入数据,也可以通过TFRecord文件导入数据(主要方法)。
利用Dataset, 可以直接乱序(shuffle), batch, padding, epoch等操作。 而不用再使用python代码去直接处理。

2.1:创建dataset:
dataset = tf.data.TFRecordDataset("test.tfrecord")
通过刚建立的test.tfrecord文件导入数据。

tf.data.TFRecordDataset()可以打开一个或多个tfrecord文件。生成一个dataset.

打开多个tfrecord文件:
例:打开目录内所有tfrecord文件:
train_files_names = os.listdir('train_file/')
train_files = ['/home/sam/palm/'+item for item in train_files_names]
dataset_train = tf.data.TFRecordDataset(train_files)
这样,就可以把多个tfrecord文件中的数据导入同一个dataset中了。


2.2:解析数据:
因为存入tfrecords文件中的数据,是序列化之后的Example. 所以,需要对数据进行解析后才能使用。也就是说,是写入时各种操作的逆操作。

2.2.1: 解析函数:
2.2.1.1: 样本解析字典:
要解析Example. 就要首先知道它包含样本的格式。由什么feature组成,feature value是何种格式保存的。
这里就用到了样本解析字典,字典的key为feature名,字典的value则是对应的feature解析方式。

解析方式有两种:
A. 定长特征解析:
tf.FixedLenFeature(shape, dtype, default_value=None)
用于解析固定长度特征。只要知道数据类型和shape,那数据长度就固定了。
所以参数shape用来指定把此feature的数据解析为何种shape.  而dtype则指定数据的类型,类型是tf.float32, tf.int64, tf.string中的一种(与feature value取值部分对应)。

B.不定长特征解析:
tf.VarLenFeature(dtype)

样本解析字典:
dics = {'scalar': tf.FixedLenFeature(shape=(), dtype=tf.int64, default_value=None), 
             
            # when parse the example, shape below can be used as reshape, for example reshape (3,) to (1,3)
            'vector': tf.FixedLenFeature(shape=(1,3), dtype=tf.float32), 
            
            # we can use VarLenFeature, but it returns SparseTensor
            'matrix': tf.VarLenFeature(tf.float32), 
            'matrix_shape': tf.FixedLenFeature(shape=(2,), dtype=tf.int64), 
            
            # tensor在写入时 使用了toString(),shape是()
            # we first set the type as tf.string, then change to its original type: tf.uint8
            'tensor': tf.FixedLenFeature(shape=(), dtype=tf.string), 
            'tensor_shape': tf.FixedLenFeature(shape=(3,), dtype=tf.int64)}

和之前写入时一一对应。
其中 Key=vector项,写入时,数据shape为(3,), 解析时,修改为(1,3).


2.2.2: 解析一个Example:
tf.parse_single_example(
    serialized,
    features,
    name=None,
    example_names=None,
)
serialized: a single serialized Example
features: 样本解析字典。

返回一个字典,key是feature名。 value是feature值。 其中value的格式,由样本解析字典定。


2.2.3:初步处理feature:
因为一些数据是转换为string, 或者因为使用不定长特征解析(解析出的是SparseTensor)。要转换回来。 还有就是要改变shape.







利用解析函数,生成新的dataset. 这个数据集,是被解析过得。
new_dataset = dataset.map(parse_function)


建立迭代器,每次取出一个Example.
iterator = new_dataset.make_one_shot_iterator()
next_element = iterator.get_next()


利用dataset做shuffle:


shuffle_dataset = new_dataset.shuffle(buffer_size=10000)
iterator = shuffle_dataset.make_one_shot_iterator()
next_element = iterator.get_next()


 batch:

batch_dataset = shuffle_dataset.batch(4)iterator = batch_dataset.make_one_shot_iterator()next_element = iterator.get_next()

 

Matplotlib学习记录

$
0
0
作者: Sam(甄峰) sam_code@hotmail.com

Matplotlib是一个用来绘制二维图像的Python库。在机器学习中很常用,主要用来数据可视化绘图,把数据直观的呈现出来。它可以绘制线图,散点图,等高线图,条形图,柱状图等等。
中文官网为: https://www.matplotlib.org.cn/


1. 画线:
使用matplotlib.pyplot 中的plot()
例如:
import matplotlib.pyplot as plt
import numpy as np
import random 

X_Data = np.linspace(0, 100, 3)
Y_Data = []

for i in range(X_Data.shape[0]):
    Y_Data.append(random.randint(0, 10))

print("X_Data:",X_Data)
print("Y_Data", Y_Data)
fig = plt.figure()
plt.plot(X_Data, Y_Data, 'bo')
plt.plot(X_Data, Y_Data, 'r-.')

plt.show() 

说明:
plt.figure() 创建一个新画布。
plt.plot() 画线,


    plot([x], y, [fmt], data=None, **kwargs)
          plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
画一条和多条线的方式。
当[x], y 只有一个输入列表或数组时,参数被当做Y轴,X轴以index自动生成。

fmt:
一个字符串来定义图的基本属性如:颜色(color),点型(marker),线型(linestyle),具体形式  fmt = '[color][marker][line]'

颜色:
    =============    ===============================
    character        color
    =============    ===============================
    ``'b'``          blue 蓝
    ``'g'``          green 绿
    ``'r'``          red 红
    ``'c'``          cyan 蓝绿
    ``'m'``          magenta 洋红
    ``'y'``          yellow 黄
    ``'k'``          black 黑
    ``'w'``          white 白
    =============    ===============================
 点型参数**Markers**,如:marker='+' 这个只有简写,英文描述不被识别
=============    ===============================
    character        description
    =============    ===============================
    ``'.'``          point marker
    ``','``          pixel marker
    ``'o'``          circle marker
    ``'v'``          triangle_down marker
    ``'^'``          triangle_up marker
    ``'<'``          triangle_left marker
    ``'>'``          triangle_right marker
    ``'1'``          tri_down marker
    ``'2'``          tri_up marker
    ``'3'``          tri_left marker
    ``'4'``          tri_right marker
    ``'s'``          square marker
    ``'p'``          pentagon marker
    ``'*'``          star marker
    ``'h'``          hexagon1 marker
    ``'H'``          hexagon2 marker
    ``'+'``          plus marker
    ``'x'``          x marker
    ``'D'``          diamond marker
    ``'d'``          thin_diamond marker
    ``'|'``          vline marker
    ``'_'``          hline marker
    =============    ===============================
线型参数**Line Styles**,linestyle='-'

    =============    ===============================
    character        description
    =============    ===============================
    ``'-'``          solid line style 实线
    ``'--'``         dashed line style 虚线
    ``'-.'``         dash-dot line style 点画线
    ``':'``          dotted line style 点线


例2:
x = np.linspace(0, 2, 100)
fig1 = plt.figure()
plt.plot(x, x, label='linear',linewidth=1)
plt.plot(x, x**2, label='quadratic',linewidth=5)
plt.plot(x, x**3, label='cubic')

plt.xlabel('x label')
plt.ylabel('y label')

plt.title("Simple Plot")

plt.legend(loc="best")

plt.show()

说明:
plt.legend(): 图例.


plt.xlim((0,1))  #x轴只截取一段进行显示
plt.ylim((0,1))  #y轴只截取一段进行显示


2. 画散点
plt.scatter(x, y)

例如:
dots1 = np.random.rand(50)
dots2 = np.random.rand(50)

plt.scatter(dots1,dots2, c="red", alpha=0.6)
plt.show()


3. 画直方图:
x = np.arange(10)
y = 2**x + 10
plt.bar(x, y, facecolor="#9999FF", edgecolor="black")
plt.show()



 

Ubuntu下Python工作环境摸索

$
0
0
作者:Sam(甄峰)  sam_code@hotmail.com

基于机器学习的学习和开发中,很多时候需要以Python和Python Package为基础,做数据准备,训练和推理。
之前一直做Linux/Android开发,对机器学习工作只触及多层感知机(NN)的训练和推理,基于OpenCV的MLP就可以了。随着对深度学习的进一步接触,深感需要一个方便合理高效的开发环境。现摸索如下。

平台的选择:
硬件:基于现有资源。
系统:为了未来训练时更高效,采用Ubuntu, 安装Cuda.

Python包和环境管理工具:
之前在windows上就使用Anaconda,深感其直观,方便。 Jupyter也令人映像深刻。所以继续采用之。

又因为pip安装的Python Package, 并不能直观显示在Anaconda界面上,所以尽量选择conda安装。

当前的工作模式是:
简单的Python程序,直接使用Anaconda中的Jupyter开发维护,运行。
PaddlePaddle, PaddleHub等使用,也是同样。

较为复杂的Python程序,或下载的Python程序......




 

Python使用记录二

$
0
0
作者: Sam(甄峰)   sam_code@hotmail.com

Python 有个语法糖(syntactic sugar)叫做list comprehension(列表推导式). 主要利用一个已知List推导新的List。

语法规范为:
out_list = [out_express for out_express in input_list if out_express_condition]

它主要用来对已知List进行过滤,转换或者组合,产生新的List。

其中,if那一块是可选的。

例1:
list_data = [1,2,3,4,5,6,7,8,9,10]
list_J = [dat for dat in list_data if (dat%2)== 0]
print(list_J)

结果是:
[2, 4, 6, 8, 10]


例2:
没有if 部分的例子:
list_sq = [x*x for x in list_data]
print(list_sq)

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]


例3:
复杂的用法,两层for循环:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

flattened = [i 
             for row in matrix 
             for i in row
            ]
print(flattened)

[1, 2, 3, 4, 5, 6, 7, 8, 9]

例4:
l_1=[2,4,6]

l_2=[1,3,5]

add = [vec[i]+vec2[i] for i in range(len(vec))]

print(add)

结果:
[3, 7, 11]







 

机器学习中的数据处理--基于Python数据结构和处理

$
0
0
作者: Sam (甄峰)   sam_code@hotmail.com

机器学习中常用的数据类型如:向量(vector), 矩阵(Matrix), 张量(Tensor)。 他们在Python中如何创建,维护和处理。尝试记录如下。

Python原生数据结构中,并没有对这些类型进行定义。所以我们通常采用Python Package numpy中最主要最常用的数据结构---ndarray(多维数据)来模拟之。 对数据的数据,则可以采用scipy package.


1. 向量(vector):
numpy 可以创建多维数组(ndarray).只需要创建一个一维数组,即可模拟vector.
既可以创建行向量,也可以创建列向量。
vector_row = np.array([1, 2, 3, 4])
print("vector_row:\n", vector_row)
print("shape:", vector_row.shape)
print("type:", type(vector_row))
print("")

vector_column = np.array([[1], [2], [3], [4]])
print("vector_column:\n", vector_column)
print("shape:", vector_column.shape)
print("type:", type(vector_column))


vector_row:
 [1 2 3 4]

shape: (4,)
type:  numpy.ndarray
vector_column: [[1] [2] [3] [4]]
shape: (4, 1)
type: nupy.ndarray



2. 矩阵(Matrix):
2.1:矩阵的创建:
numpy可以创建多维数组(ndarray). 创建一个二维数组,即可模拟matrix.

#Matrix
matrix_int = np.array([[1,2], [3,4], [5,6]])
print("matrix_int:\n", matrix_int)
print("shape:", matrix_int.shape)
print("type:", type(matrix_int))

matrix_int:
 
[[1 2] [3 4] [5 6]]
shape: (3, 2)
type:numpy.ndarrdy




numpy也提供了专门的数据结构来表示矩阵--numpy.matrix
mat_object =np.mat([[1,2], [3,4], [5,6]])
print("mat_object:\n", mat_object)
print("shape:", mat_object.shape)
print("type:", type(mat_object))

mat_object:
 
[[1 2] [3 4] [5 6]]
shape: (3, 2)
type: numpy.matrix


关于矩阵是使用2D array 还是 numpy.matrix. 很多人推荐使用2D array. 首先, array才是numpy的标准数据结构。 其次,绝大多数numpy操作返回的是array而不是numpy.matrix 对象。


2.2: 稀疏矩阵
若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。



矩阵的稀疏性可以用一个得分来量化,也就是矩阵中零值的个数除以矩阵中元素的总个数。
机器学习中,有大量稀疏矩阵的例子,例如:
用户是否在一个电影目录中有曾经看过的电影。
用户是否在一个产品目录中有已经购买过的产品。
在一个歌曲目录中数出收听过的歌曲的数量。

2.2.1: 稀疏的问题:
稀疏矩阵会导致两个问题: 空间复杂度,时间复杂度。
非常大的矩阵,需要大量的空间存储。而只是对资源的浪费,因为0值不包含任何有意义的信息。
而巨大的矩阵,计算有很耗费时间。

因为稀疏矩阵导致问题,而机器学习领域稀疏矩阵很常见,所以必须想办法处理之。
直观的想法就是使用另一个节约空间的方法来表示稀疏矩阵。零值被忽略,只记录非零值。

多个数据结构可以用来有效地构造一个稀疏矩阵;下面列出了三个常见的例子。

Dictionary of Keys。在将行和列索引映射到值时使用字典。
List of Lists。矩阵的每一行存储为一个列表,每个子列表包含列索引和值。
Coordinate List。一个元组的列表存储在每个元组中,其中包含行索引、列索引和值。
还有一些更适合执行高效操作的数据结构;下面列出了两个常用的示例。

压缩的稀疏行。稀疏矩阵用三个一维数组表示非零值、行的范围和列索引。
压缩的稀疏列。与压缩的稀疏行方法相同,除了列索引外,在行索引之前被压缩和读取。
被压缩的稀疏行,也称为CSR,通常被用来表示机器学习中的稀疏矩阵,因为它支持的是有效的访问和矩阵乘法。

Python Package ---scipy提供了使用多种数据结构创建稀疏矩阵的工具,以及将稠密矩阵转换为稀疏矩阵的工具。许多在numpy和scipy函数可以透明的操作scipy稀疏数组。 scikit-learn和Keras也可以透明的操作scipy稀疏数组。

NumPy数组中的稠密矩阵可以通过调用csr_matrix()函数将其转换为一个稀疏矩阵。



NumPy并没有提供一个函数来计算矩阵的稀疏性。
但可以方便的计算出。
因为numpy可以计算出ndarray中的非零个数。
np.count_nonzero(matrix_data)





3. 对Vector, Matrix的操作:
3.1: 对多个元素同时应用某个操作
对一个array中的多个元素同时应用于某个函数。
可以利用numpy的vecotrize (函数的向量化)来解决。

numpy的vectorize类将一个函数转换成另一个函数,这个函数能把某个操作应用于数组的全部元素或者一个切片上。


3.2: 找到ndarray中的最大值和最小值
使用numpy的max和min方法。

matrix_data1 = np.array([[1,2,3],[4,5,6],[7,8,9], [101112]])
print("max is:",np.max(matrix_data1))
print("min is:", np.min(matrix_data1))

max is: 12
min is: 1

numpy的max和min方法支持对一个特定轴向取最大最小值。



3.3: 获取ndarray的平均值,方差和标准差
方差和标准差,是度量一组数据和其平均值之间的散布程度的测量。

方差:
方差用来计算每一个变量(观察值)与总体均数之间的差异。为避免出现离均差总和为零,离均差平方和受样本含量的影响,统计学采用平均离均差平方和来描述变量的变异程度

标准差:
标准差(Standard Deviation),在概率统计中最常使用作为统计分布程度
(statistical dispersion)上的测量。标准差定义是总体各单位标准值与其平均数
离差平方的算术平均数的平方根。它反映组内个体间的离散程度。


方差和标准差的关系: 标准差是离均差平方的算术平均数(即:方差)的算术平方根,用σ表示。




numpy的mean, var和std方法。



3.4:矩阵的变形
在不改变元素值的情况下,改变一个ndarray的形状(行数和列数)
使用numpy的reshape。

reshape方法可以重构一个数组,维持该数组原来的数据不变,只改变行数和列数。但要求原数组和新数组元素个数必须相同。



reshape()特殊的参数:
-1: 

只有一个整数作为参数:

把矩阵展开,即转换为一个一维数组:
方法一:
reshape(1, -1)
方法二:
flatten.


3.5: 矩阵和向量的转置:
使用T方法。


3.6:矩阵的秩
可以使用numpy中的线性代数方法 matrix_rank.

但没明白ndim和rank的区别。


3.7: 矩阵行列式
numpy的det


3.8:获取矩阵的对角线元素
diagonal

3.9:矩阵的迹
其对角线元素之和
trace



3.10:方阵的特征值和特征向量



3.11: 两个向量的点积

3.12: 矩阵的相互加减


3.13:矩阵的乘法


3.14:矩阵的逆


3.15:产生随机数


 



附录:










 

机器学习之模型评估

$
0
0
作者: Sam(甄峰)  sam_code@hotmail.com

0. 问题的提出:
对一个机器学习模型,如何评估其好坏。最好有个指标性的数据。

对一些分类模型,首先可以想到使用精准率,如:有90%的分类是准确的。但这个数据在某些情况下,并不足以反映真实情况。

1. 分类评估指标:
1.1:准确率(Accuracy):
它是一种常见的性能指标,表示被正确预测的样本数占参与预测的样本总数的比例。

准确率的优点在于它有直观的解释:被正确预测的样本的百分比。
但在现实世界中,样本数据分布往往会有类别不均衡的问题。例如,99.9%的样本属于分类1,只有0.1%的样本属于分类2. 当存在类别不均衡问题时,使用准确率作为衡量标准会出现模型的准确率高但预测能力不足的情况。
例如:癌症的预测。例如整体人群中,某种癌症的发病率只有 0.1%。我们训练一个模型,准确率为95%. 但简单的创建另一个模型,预测任何人都不患这种癌症,准确率却高达99.9%。 但这个所谓模型却没有任何意义。
为了解决这个问题,我们需要其它指标数据。


如果我们建立一个图,x轴向表示为真实的分类,Y轴表示预测的分类:



TP: 真阳性。
FP:假阳性。
FN:假阴性。
TN:真阴性。

1.2:精确度(Precision):
表示所有预测为正类的样本中被正确预测的样本的百分比。
TP/(TP+FP).  这个值越高越好。
可以把它看作是:衡量预测结果中噪声多少的指标。这个值越高,噪声越少。

1.3:召回率/测准率(Recall):
所有真实为True的样本中,被预测为True的样本的百分比。
TP/(TP+FN)
召回率/测准率衡量的是模型识别证样本的能力。召回率越高,则把正样本识别为正的能力越强。


不过如果有这俩个评估值,如何抉择呢?例如:


这三个算法,如何抉择呢? 如果选择P+R的平均值,则第三个最好,但其实它正是我们想要解决的类别不平衡问题的反应。

1.4: F-Score:
2* (P*R)/(P+R)
这个公式,让P或者R中某一个值太小时,F-Score急剧变小。是个衡量正类预测的正确程度(correctness)的指标。


2. 目标检测算法中衡量指标
2.1: 几个基础概念:
2.1.1: IoU(Intersection over union):
交并比,它衡量的是两个区域的重合程度。是两个区域重叠部分面积占二者总面积的比例。

IoU通常用来计算的是“预测的边框”和“真实的边框”的交集和并集的比值。

在目标检测任务中,如果模型预测的Box和真实标注的Box的IoU超过一个阈值(如0.5).则可以认为它输出了正确结果。

2.2: 精确度(Precision)和召回率/测准率(Recall):
如果我们把超过某个IoU阈值的预测结果作为正,反之作为负。则可以直接引入Precision和Recall概念。
与前面完全相同。

2.3: PR曲线:
目标检测中,我们当然希望P和R均很高才好。但往往不能如愿,他们的结果常常是矛盾的,如何取舍?除了F-Score为,还可以用PR曲线来帮助分析决策。
实例如下:

(图取自网络,谢谢原作者)
数据按置信度排序,而Precision和Recall值,则表明如果以这一行的执行度为阈值,得到的Precision和Recall值。



以Recall值为横轴,Precision值为纵轴,我们就可以得到PR曲线。 




 

Win10下安装PaddlePaddle-GPU版本

$
0
0
作者: Sam (甄峰) sam_code@hotmail.com

之前在Linux下使用Paddle及其相关工具,之后想把它放在手头一台训练机上,但对Linux下安装Cuda信心不足。所以采用Windows。没想到也遇到一些问题,记录下来备忘。



0. 背景介绍:
0.1:训练机介绍:
主板为技嘉B85M-D3V-A. 显卡为Nvidia GeForce RTX 2070. 使用WD 1T 硬盘和一个附加硬盘盒。

0.2:Cuda安装背景:
Paddle-GPU版本,支持win7 win8, win10.
支持CUDA9.0, CUDA10.0, CUDA10.1, CUDA10.2, CUDA11.0. 
并需要安装cudnn.

所以,需求很明确:
A. 安装GeForce RTX2070 driver.
https://www.nvidia.cn/Download/index.aspx?lang=cn

B. 安装Cuda Toolkit.
https://developer.nvidia.cn/cuda-toolkit-archive
C. 安装cudnn.
https://developer.nvidia.com/rdp/cudnn-archive
D. 安装Python+pip.
https://www.python.org/downloads/windows/
E. 安装Paddle.


1. 初次尝试(踩坑SHA-2):
首先安装Win7  Professional版本。 在安装RTX2070 Driver时报错,要求安装SHA-2补丁。并指出补丁下载地址,下载后,却告知此补丁不适合当前版本。
网上有朋友指出,需要win7 sp1才可以使用此补丁。或者使用win10. 它已经将SHA-2内置。

1.1: 踩坑 Nvidia driver和Cuda版本:
Nvidia driver版本和cuda版本有其对应关系,安装driver后,需要查看其最大支持的cuda版本,再行安装,否则会产生错误如下:
(base) PS C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\extras\demo_suite> .\deviceQuery.exe
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\extras\demo_suite\deviceQuery.exe Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

cudaGetDeviceCount returned 35
-> CUDA driver version is insufficient for CUDA runtime version
Result = FAIL
这里表示driver版本与CUDA版本不匹配。

那如何知道对应关系呢? 有两个途径:
A. https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html

这里明确指出了其对应关系。




B. 






可以看到,这个driver只支持9.1.84 cuda.再高了就无法支持了。

而driver的版本是:391.35


A,B两组方法可以互相印证。





2. Win10版本+Nvidia driver + Cuda + cudnn:

2.1:安装driver.
此次安装Nvidia driver, 则没什么问题。
注意,Nvidia driver. 要选择正确的 设备和操作系统。

2.2:安装cuda toolkit:
cuda Toolkit, 则选择10.2.
https://developer.nvidia.cn/cuda-toolkit-archive
安装成功后的验证:
nvcc --version
可以看到,显示了10.2版本。

2.3:安装cudnn:
paddle中说明:CUDA 工具包9.0/10.0/10.1/10.2 配合 cuDNN v7.6.5+
所以选择 cudnn7.6.5 for cuda10.2.
https://developer.nvidia.com/rdp/cudnn-archive

下载解压后,包含bin,include,lib三个目录。
把cuda\bin\cudnn64_7.dll复制到 C:\Program Files
\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin 目录下.
b) 把\cuda\ include\cudnn.h复制到 C:\Program Files
\NVIDIA GPU Computing Toolkit\CUDA\v10.2\include 目录下.
c) 把\cuda\lib\x64\cudnn.lib复制到C:\Program Files
\NVIDIA GPU Computing Toolkit\CUDA\v10.2\lib\x64 目录下.

3. Python安装和其它相关
正常安装,记得点选加入PATH复选框。

4. 安装Paddle-GPU版本:
python -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple
验证:
import paddle
paddle.utils.run_check()
若显示类似信息,表示安装成功:
PaddlePaddle works well on 1 GPU.
W0408 12:04:04.227409  8860 build_strategy.cc:171] fusion_group is not enabled for Windows/MacOS now, and only effective when running with CUDA GPU.
PaddlePaddle works well on 1 GPUs.
PaddlePaddle is installed successfully! Let's start deep learning with PaddlePaddle now.

安装PaddleDetection
git clone https://gitee.com/paddlepaddle/PaddleDetection


安装paddlehub:
pip install paddlehub



 

PaddleDetectionPCB训练记录

$
0
0
作者:Sam (甄峰) sam_code@hotmail.com

Paddle在目标检测7日打卡营中有个作业--Yolo系列模型训练实战,训练PCB瑕疵检测。

现将训练过程记录如下:
1. 使用Yolov3_darknet_baseline.yml为基础训练:
其中:
max_iters11000
base_lr0.00025
batch_size=8
worker_num=8
后两项故意不修改,看看情况。

python -u tools/train.py -c ../zienon_config/yolov3_darknet_baseline_sam.yml -o use_gpu=true --eval --use_vdl=true --vdl_log_dir=vdl_dir/scalar3/
说明:
-c ../zienon_config/yolov3_darknet_baseline_sam.yml
采用baseline的yml文件。

--eval
表示在训练过程中进行验证。周期由yml文件中:snapshot_iter200 指定。即每200轮,保存一次模型,并验证。

--use_vdl=true --vdl_log_dir=vdl_dir/scalar3/
打开可视化工具并指定保存目录。如果指定,则可以使用VisualDL直观的看loss和mAP变化。

结果如下:
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.110 Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.422 Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.019 Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.213 Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.121 Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.006 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.055 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.237 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.239 Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.237 Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.258 Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.006 2021-04-15 14:00:30,146-INFO: Best test box ap: 0.14457301539635092, in iter: 9000

VisualDL显示:


可以看到,mAP(IoU=0.5) 的值是:0.422.

直接跑:
python -u tools/eval.py -c ../zienon_config/yolov3_darknet_baseline_sam.yml -o use_gpu=true weitht=output/yolov3_darknet_baseline_sam/best_model.pdparams
mAP也是类似。


2. 修改学习率:
base_lr: 0.001
max_iters11000
batch_size=8
worker_num=1
不知道worker_num 在单核GPU中有何意义。暂时把学习率增大看看效果。
Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.173
 Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.567
 Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.036
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.252
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.192
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.059
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.071
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.282
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.282
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.300
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.301
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.057


可以看到,随着训练轮数增加,mAP已经不再提高。

但此处疑惑的是:
从第一次训练的mAP图来看,学习率为0.00025时,mAP提高也遇到障碍,不再随着轮数提高而提高。
但第二次训练,lr提高到0.001, mAP却事实上提高了。











 

图像均值归一化

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

1:图像的均值:
对图像来说,均值分两种:Image mean,  Pixel mean.
Image mean:
把所有训练集中的图片在同一空间位置上的像素对应通道求均值。
例如:训练集是N张 W x H x C 的图片。 则Image mean是一个W x H x C 的矩阵。 其中每个值都是对应位置像素的均值。

Pixel mean:
把所有训练集中的图片的各个通道分别求均值。
例如:训练集是N张 W x H x C 的图片。则Pixel mean是 C个值。 如:R_mean.  G_mean, B_mean.

2. 去均值:
为什么要去均值。可以从两个方面看:
A. 从主成分分析(PCA)角度看:
数据特征需要标准化, 使的数据的每一个维度都有零均值和单位方差。
在实际使用中,特征标准化的具体做法是:
  计算每个维度的均值。
  在每个维度减去均值。形成零均值。
  在每个维度除以该维度的标准差。
但对自然图像数据,更多的是图像各个channel的零均值。并不需要除以样本的标准差。

对于图像,这种归一化可以移除图像的平均亮度(intensity). 因为我们常常对图像的照度并不关心。

B. 从深度学习反向传播角度看:
机器学习中,若两个特征取值范围相差极大(跨数量级), 则代价函数J()会很扁,梯度下降时收敛不好。此时,需要做特征缩放(Feature Scaling). 把各个特征值的取值范围压缩到同一维度。 例如:   0 < 1.
通常可以做均值归一化。 
例如:某个维度数据 X, 它的均值是M。 最大值为x_max, 最小值为  x_min.
s=x_max - x_min.
均值归一化则是: (x - M)/s.
s也可以取标准差。(这里与PCA对应起来)

深度学习中, 一般把喂给网络模型的训练数据进行预处理, 使用最多的方式是零均值(Zero-mean). 即让所有训练集图片中每个像素的均值为0. 使得像素范围 [-128, 127], 以0为中心。 这样是为了在反向传播中加快网络中每一层权重参数的收敛。

在Tengine中,有参数mean, scale.
代码中的做法是,(像素值-mean)*scale.
mean是对应channel的均值,通常是127.5, 128等。 
scale通常是1/256 ,  1/255,  1/127 , 1/128等等。
逻辑和图像均值归一化类似。



 

Python3多国语言处理

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

在Python中遇到中文或多国语言,常常会遇到字符编码问题。现将其记录如下:

0. Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4等缘起和概念
世界各国都有各自的文字编码集,互不兼容,相同的编码值,在不同的语言文字编码集中代表不同的符号。因此,同一份文档copy到不同语言的机器中,就可能显示乱码,无法阅读。于是,就有了一个需求:定义一个超大的字符集,包含全世界所有文字字符,让每种语言的每个字符都对应唯一的编码值。

有两个不同的机构分别作出了自己的标准:
A. 国际标准化组织(ISO), 在1984年尝试制定通用字符集(Universal Character Set) UCS.  即为ISO 10646标准。
B. 统一编码联盟。 发起了Unicode标准。

之后,双方尝试合并工作成果。从Unicode 2.0开始, Unicode采用了与ISO 10646标准相同的字库和字码。 ISO 10646也将不会为超出10FFFF的UCS-4编码赋值。 以使得两者保持一致。

0.1: UCS-4 和 UTF-32:
ISO 10646标准为通用字符集(UCS)定义了一种31位的编码 UCS-4. 其编码固定占用4个字节,编码空间为:0x0000000-0x7FFFFFFF. 共可以编码2的31次方个字符(2147483648)。
但其实使用范围不超过0x10FFFF个。且为了兼容Unicode标准。ISO也承诺将不会为超出范围的USC-4编码赋值。
UTF-32编码的编码值与UCS-4相同。

0.2: UCS-2和UTF-16:
除了UCS-4, ISO 10646标准为通用字符集(UCS)定义了一种16位的编码形式---UCS-2. 其编码固定占用2字节。所以包含65536个编码空间。为了兼容Unicode, 0xD800-0xDFFF之间的编码未使用。所以它只支持63K个常用字符编码。
UTF-16则稍有不同,它使用2个字节对全世界最常用的63K字符编码(与UCS-2的常用编码相同),使用4个字节对不常用的字符进行编码,数据变长编码。所以它可以为Unicode中所有字符进行编码。

0.3:UTF-8
UTF-16, UTF-32都需要多个字节表示一个字符编码。对纯粹英语字符有些浪费。所以有了UTF-8.
它的原则是:ASCII码中的字符,还是ASCII码的值,只需要一个字节表示。其它的Unicode字符集中的字符编码,则使用2,3,4字节来表示。

0.4:Unicode与UTF-8, UTF-16, UTF-32的关系:
Unicode是一个字符集,包含全世界所有的字符。
而UTF-8, UTF-16, UTF-32则是对Unicode中所有字符的不同编码方式。

1. Python2和Python3的Unicode问题
Python3 里有两种表示字符序列的类型,分别是 bytes 和 str,bytes 的实例包含 8 位值,str 的则包含 Unicode 字符。
Python2 中也有两种表示字符序列的类型,分别是 str 和 Unicode. str 的实例包含原始的 8 位值,而 Unicode 的实例包含 Unicode 字符。这是什么意思呢?也就是说 Python3 中字符串默认为 Unicode,但是如果在 Python2 中需要使用 Unicode,必须要在字符串的前面加一个 「u」前缀.






 

NPU相关知识

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

0. 基础概念:
0.1:OpenVX:
各种硬件厂商生产的芯片结构和功能区别很大,同样的代码,在不同硬件上实现的性能有很大区别。所以想要最大限度发挥硬件性能,必须针对硬件本身进行代码优化。所以一份算法程序,在不用硬件上经过优化的代码是不同的,这对开发者造成很大困扰。(主要指视觉领域)
为了解决这个问题,硬件厂商(Intel, AMD, TI 等)通过Khronos Group组织制定一个跨平台标准以解决这个问题。类似的跨平台标准包括:OpenCL, OpenGL等。
如此,则硬件设备不同导致代码的差异由厂商自己实现,算法开发者只需要关注算法本身。

图像处理,就是对图片矩阵进行一系列操作,从中获取结果。每一种对图像的基本操作都可以看成一个node, 很多Node相连,就组成一个graph. 
vendor就是针对自己的硬件实现node的代码,使之符合OpenVX的标准并优化。
开发者用代码将Node连接成Graph。
Vendor再针对自己的硬件优化加速graph.


与OpenCV的区别:
OpenCV偏向于用software的方式来实现一些定义的功能,而OpenVX是一些标准的API,系统第三方Vendor用硬件来实现一些图像处理功能,以提高效率。


0.2:TIM-VX:
芯原电子(VeriSilicon)是国内的一家NPU IP供应商,它开源了TIM-VX(Tensor Interface Module for OpenVX). 用来在支持OpenVX的自研ML 加速IP上实现深度学习神经网络模型部署。
可以作为Android NN, TensorFlow-Lite, MLIR, TVM, Tengine等runtime Inference Framework的backend模块。

0.3: 国内AI边缘计算芯片
包含NPU的有: 
Amlogic : S905D3, A311D, C308X. 使用:
Rockchip: RK3399Pro, rv1109 rv1126等。 使用: RKNN API.
海思; HI35xx  HIAI API


 

Yolo简介及其推理

$
0
0
作者:Sam (甄峰)  sam_code@hotmail.com

0.目标检测算法:
目标检测算法两个分支,单阶段和两阶段目标检测



Yolo(You Only Look Once)是目标检测单阶段模型。它是一个精度尚可,速度很快的模型。即精度速度性价比很高的模型。

1. Yolo的思路
如何可以只Look一次呢? 就是将目标检测当作一个单一的回归任务。

1.1:核心思路:
A. 将图像划分为SxS个网格。
B. 物体的真实框中心落在哪个网格,就由该网格对应的Anchor负责检测该物体。

1.2:模型输出
输出W x H x C:
W 和H,代表划分的网格数(S x S). 例如13x13.
C通道上,则存储 x, y, h, w, project, classification(one-hot).

1.3:模型特点:
骨干网络使用DarkNet. YoloV3采用了DarkNet53 
采用全卷积网络结构: Conv+Batch Norm.
Kmeans聚类产生9个Anchor.
多尺度训练。跨尺度特征融合。 
分类使用sigmoid激活,支持目标多分类。

2. 模型详解:
2.1:Yolo模型结构:


骨干网络采用Darknet53, 分5个阶段,每个阶段使用倍数为2的下采样。
最后分别输出32倍,16倍,8倍下采样。共3个特征图。


2.2:模型的输入和输出:



输入:shape为[N, 3, 416, 416].
N 为batch size.
3: RGB三通道
416, 416:输入图像的H,W.


共输出三个特征图,分别对应32,16,8倍下采样。
416/8=52,  416/16=26  416/32=13.
所以对应的特征图的w和h 分别是13x13,  26x26, 52x52.
每个特征图分配3个锚框。

2.3:锚框(Anchor)和它存在的理由:


锚框,Anchor:就是用KMeans聚类,在训练集上聚类出的一些框,给定HW. 这些框,表示了物体最有可能出现的长宽。是一个先验框。

Yolo把最大的三个Anchor分配和视野最大的一个特征图,把最小的三个Anchor分配和视野最小的一个特征图。
所以,Yolo的每个输出特征图,都会分配3个Anchor.  这样预测框仅需要在锚框的基础上微调,就可以更快的找到和表达真实框。

2.4:从锚框(Anchor)到预测框:
在特征图的每个网格中(SxS), 都放入分配给它的锚框--通常是3个。
例如:13x13的网格中,每个网格都分配给3个较大的Anchor.

所以,预测框的数量为:
网格数 x 分配给它的锚框数 --->13x13 x3

每个预测框的数据包括:x, y, h, w , p + class_num 
5 + class_num 




3. Yolo的预测流程:


获得了(13x13 + 26x26 + 52x52) *3个 class, score, x, y, w, h后。再做NMS, 把重复的预测框去掉。



即先按class分类, 再按score排序, 之后从score高的到score低的计算IoU,如果高于某个阈值,则表明它们意见相同,表示的是同一个真实框,则把score低的去掉。

最后保留下来的就是预测的真实框。


4. YoloV3-Ting:
对于速度要求较高的项目,可以选择YoloV3_tiny.
它在Yolo基础上去掉了一些特征图,只保留了两个独立的预测分支。
N, 255, 13, 13
N, 255, 26, 26
其中255是class_num=80时计算的。实际情况根据class_num计算。



5. 使用OpenCV DNN推理
可以使用OpenCV DNN 来推理Yolo模型。

5.1:打开模型:
因为骨干网络是darknet
auto net = cv::dnn::readNetFromDarknet(models_cfg, models_weights);

这是Yolo的特殊点:
std::vector vecOutNames =  net.getUnconnectedOutLayersNames();


5.2:准备数据:
matInputBlob = cv::dnn::blobFromImage(matFrame, 1 / 255.F, cv::Size(416, 416), cv::Scalar(), true, false);
可以看到,归一化的mean={0, 0, 0}
scale=1/255.
输入Mat resize成  416x416.

5.3:指定数据:
net.setInput(matInputBlob);

5.4:推理:
net.forward(vecOutMat, vecOutNames);
Yolo输出就在vecOutMat中。

后面就要根据Yolo的输出特征图格式,来解析输出数据,得到推理出来的预测框了。

5.5:输出特征图的数据分析:
vecOutMat.size(), 有多少个输出分支,它的size就多大。如果采用Yolo,则有3个分支。如果采用Yolo_tiny, 则有两个分支。

vecOutMat[i].rows, vecOutMat[i].cols:
分别表示这个分支上预测框的个数,以及每个预测框的具体信息。
vecOutMat[i].rows--此分支上预测框个数。 按之前所说: 网格数 x 分配给它的锚框数 --->13x13 x3
则表明这个分支上预测框个数为: 13x13x3.
vecOutMat[i].cols:每个预测框的内容。其中包括: x, y, w, h, p + class_id(one-hot)
例如:如果是个4分类的模型,则有5+4共9 位。

NMS:
cv::dnn::NMSBoxes(vecBoxesRect, vecConfidences, 0.5, 0.2, vecIndices);
把所有符合条件的预测框填入vecBoxesRect, 对应的Score填入vecConfidences. 进行NMS. 
NMS结果会填入最后一个参数。参数中是索引值。


6. 使用Tengine_Lite推理














 

Ubuntu开发机配置

$
0
0
作者:Sam (甄峰)  sam_code@hotmail.com
0. 安装Ubuntu
Install use bootable Ubuntu usb devices:
采用rufus做一个U盘启动和安装盘。
https://rufus.ie/en/

1. ssh-server安装:
sudo apt install openssh-server

查看是否安装成功,可以用以下两个方法。
apt list --installed |grep ssh
dpkg -l |grep ssh

若显示已经有openssh-server, 则表明安装成功。


其从ssh server:
sudo service ssh start


2. 安装samba-client:
sudo apt-get install smbclient

create mount_dir
#mkdir /home/sam/samba_dir
#sudo mount -t cifs //192.168.31.122/sam /home/sam/samba_dir -o username=android,password=123456

















附1.  Advanced Packaging Tool(APT)和Debian Packager(dpkg)
dpkg是Debian Pakager的简写。 是Debian专门开发的套件管理系统,方便软件的安装,更新和删除。 所有源自Debian的Linux发型版本都使用dpkg. 如Ubuntu, Knoppix等。与Fedora的rpm类似。用于安装,卸载 .deb软件包,并能获取.deb信息。

安装: 
安装一个.deb:
dpkg -i  .deb_file
安装一个目录下所有软件包:
dpkg -R  /home/sam/deb/

删除:
删除但保留配置信息:
dpkg -r
删除包和配置信息:
dpkg -P 

显示已安装软件包:
dpkg -l 
例:查找已安装的ssh相关软件包
dpkg -l |grep ssh

查找已安装的软件包在何处
dpkg -L 
例如: dpkg -L openssh-client


Advanced Packaging Tool是Linux下一款安装包管理工具(apt, apt-get apt-cache)。
dpkg虽然可以管理软件包。但对软件的依赖关系等没有处理。且与ubuntu软件仓库没有联系。所以可以使用apt工具。
apt包括: apt, apt-get, apt-cache,apt-config
apt是新版本,包含apt-get, apt-cache, apt-config的功能。

安装:
apt install 

卸载:
apt remove  (保留配置)
apt purge (连带配置删除)

显示已安装软件包:
 apt list --installed


附2: 修改gcc g++版本:
ubuntu20.04缺省gcc g++版本是 9. 会导致如cuda无法安装。 需要将其降低。

sudo apt-get install gcc-7 g++-7
 
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 1
 
sudo update-alternatives --display gcc
 
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 9
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 1
 
sudo update-alternatives --display g++

此时:
gcc --version

gcc (Ubuntu 7.5.0-6ubuntu2) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.





 

Ubuntu20.04安装Cuda+cudnn

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

在Ubuntu20.04下安装深度学习训练环境记录。

0. 硬件环境:
主板为技嘉B85M-D3v-A. 显卡为Nvidia GeForce RTX2070. 准备使用Ubuntu20.04。

1. 安装:
1.1:背景介绍:
A.首先需要安装Nvidia GetForce RTX2070显卡驱动。
B. 需要安装Cuda Toolkit. 
C. 需要安装cudnn.(训练加速工具)

其中要注意: 
A. Nvidia driver和Cuda toolkit之间有匹配关系,版本选择上要注意。
B. Cuda Toolkit和cudnn有匹配关系。版本选择要注意。
C. 深度学习框架,通常会需要匹配Cuda Toolkit和cudnn版本。

Nvidia Driver和Cuda Toolkit的匹配关系请查看:
https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html
driver版本过低,则无法支持高版本cuda.


1.2:安装driver:
1.2.1:首先确认是否存在Nvidia 显卡:
#lspci |grep NVIDIA
如果有NVIDIA设备,则会显示,例如,机器上安装有RTX2070,则显示如下:
01:00.0 VGA compatible controller: NVIDIA Corporation TU106 [GeForce RTX 2070 Rev. A] (rev a1)
01:00.1 Audio device: NVIDIA Corporation TU106 High Definition Audio Controller (rev a1)
01:00.2 USB controller: NVIDIA Corporation TU106 USB 3.1 Host Controller (rev a1)
01:00.3 Serial bus controller [0c80]: NVIDIA Corporation TU106 USB Type-C UCSI Controller (rev a1)


1.2.2:安装Nvidia driver:
可以利用Ubuntu的 Software and Update 来安装驱动。

这里选择 nvidia-driver 470版本。

验证
nvidia-smi


可以看到Driver Version : 470.
此处的CUDA Version:11.4. 并非表明已经安装cuda. 只是表示此版本Nvidia Driver最高支持的Cuda Toolkit版本号。

1.3: 安装Cuda Toolkit:
1.3.1:Cuda Toolkit与 Nvidia Driver的对应关系:
Nvidia不同的硬件,可以匹配的driver版本不同,一些比较老driver版本,也只能支持比较老的Cuda Toolkit版本。其对应关系可见:
https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html



可以看到,Sam安装的470.86 driver,最高支持Cuda Toolkit 11.4. 


当然,nvidia-smi中显示的cuda version:即为此版本driver支持的最高Cuda Toolkit版本。

1.3.2:安装:
https://developer.nvidia.com/cuda-toolkit-archive
按实际情况选择对应版本:


按说明:
wget ....

sudo sh cuda_11.2.0_460.27.04_linux.run

安装成功过后。需要把bin目录加入PATH, 把libray目录加入LD_LIBRARY_PATH.

#sudo vi ~/.profile 
添加:
export PATH=$PATH:/usr/local/cuda-11.2/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-11.2/lib64

#bash -login
则profile起效了。


1.4:安装cudnn:
cudnn和cuda toolkit有对应关系。
https://developer.nvidia.com/rdp/cudnn-archive
选择对应的版本下载。

把头文件和库文件copy到对应位置:
#sudo cp include/cudnn*.h /usr/local/cuda-11.2/include/
#sudo cp lib64/* /usr/local/cuda-11.2/lib64/


































 

LabelImg使用简介

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

背景:
LabelImg是一个图像化图像标注工具(annotation tool). 它是用Python写成的,用QT作为其图形界面。
LabelImg支持以PASCAL VOC格式保存XML标注文件,这是ImageNet所使用的格式。此外,它还支持YOLO和CreateML格式。

在Ubuntu安装使用如下:

1. 安装基础工具
使用前,需要先安装Python, qt. (这里选用Python3)
#python3 --version
python 3.8.10


sudo apt install pyqt5-dev-tools
sudo apt install pip
sudo pip3 install lxml

2. download labelImg and make:
git clone https://github.com/tzutalin/labelImg.git
or : git clone https://gitee.com/monkeycc/labelImg.git

export LC_ALL=C
make clean;make


3. 使用:
#python3 labelImg.py



View->Auto Save mode
OpenDir
Change Save Dir.

PascalVOC/YOLO/CreateML

D
A
W


 

git使用记录本地

$
0
0
作者:Sam(甄峰)  sam_code@hotmail.com

1. 提交:
提交记录,git仓库中保存的是您目录下所有文件的快照,就像是把整个目录复制,然后再粘贴一样,但比复制粘贴优雅的多。
git 希望提交记录尽可能的轻量,因此再每次进行提交时,它并不会盲目的复制整个目录,条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。
#git commit

以图为例:

仓库中有提交记录,初始提交记录C0和在它基础上修改的提交记录C1.

执行#git commit

生成一个新的提交记录C2. 它的父节点是C1.

2. 分支:
git的分支非常轻量,他们只是简单的指向某个提交记录。
建立分支并不会造成储存或内存上的开销。使用分支其实就相当于“基于这个提交以及它所有的父提交进行新的工作“。 它与commit协作,能够极大的降低维护成本。
#git branch

例如:
某厂商要建立创维和海尔两个分支,并在其上分别开发。

当前有C0和C1两个提交。
当前想在C1这个节点创建haier和skyworth两个分支。
#git branch haier
#git branch skyworth

可以看到,此处的节点并没有增加,这就是:"只是简单的指向某个提交记录"的意思。
main后面的* 表示当前所在分支是main.  所在分支是哪个,则commit就在哪个分支上。


现在我们往main分支提交一个节点
#git commit 

可以看到,因为当前所在分支是main. 所以提交后,新的节点是main的。 但haier和skyworth还停留在老节点上。如果要haier和skyworth上有新提交。需要首先切换当前分支。


#git checkout haier


可以看到,当前分支是haier。 现在commit,则在haier上提交了

#git commit



同样,可以切换当前分支为skyworth并提交:
#git checkout skyworth
#git commit




3. 分支合并:
要把分支合并进来,可以使用多种方式:
方法一:
#git merge
就可以把指定的branch_name 合并到当前分支了。

当前状态:


#git checkout -b bugFix
#git commit
#git checkout main
#git commit
#git merge bugFix

结果如下:



方法二:
#git rebase










 

git使用记录二远程部分

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

上一节中,我们聚焦在本地仓库的操作(branch, merge, rebase等),这一节看看远程仓库。
远程仓库并不复杂,只是你的仓库在另一个计算机上的拷贝。同样可以提交和恢复项目到指定版本的能力。但因为项目被托管到远端,所以可以多人对项目做出贡献。

现在用网站对远程仓库进行可视化操作的有: github, phabricator.

1. 在本地创建一个远端仓库的拷贝:
#git clone 



 
Viewing all 158 articles
Browse latest View live