题目:有大小为256*256和32*32的两个二维数据数组,其数据分别保存在raw.txt文本文件(源数据)和obj.txt文本文件中(目标数据)。请采用一种距离度量,从源数据中寻找与目标数据的距离最小的前10个数据块(寻找到的每个数据块与目标数据的维数相同,即32*32的数组)。距离的大小,反映了搜索到的数据块与目标数据之间的相似程度,例如,如果搜索到的数据与目标数据完全相同,则它们之间的距离为0,如果搜索到的数据块与目标数据不同,则它们之间的距离大于0,距离越大,表明它们之间的相似程度越小。
-
程序功能说明:
-
先从raw.txt文本文件(源数据)和obj.txt文本文件(目标数据)中得到255*255的数组和32*32的数组(这里的数组是指python意义上的数组,序号从0开始);
关键代码如下:
obj_data = np.loadtxt("obj.txt")
raw_data = np.loadtxt("raw.txt")
-
把255*255数组分成一个一个的32*32数据块的;
关键代码如下:
for i in range(i, i+33):
for j in range(j, j+33):
arr1[count]=raw_data[i][j]
count+=1
if j==n_j+32:
j=n_j
arr2=list(arr1.values())
-
把32*32的目标数组变成一维数组,数组共有33*33=1089个元素,把32*32数据块的也变成一维数组;
关键代码如下:
32*32的目标数组转为一维数组
obj = [i for item in obj_data for i in item]
32*32的数据块转为一维数组
arr2=list(arr1.values())
-
在计算相似度;
关键代码如下:
x = obj
y = arr2
sum_XYSimlar = 0
for i in range(0, len(x)):
# 两个数的欧几里得距离
XYdistiance = np.sqrt(np.sum(np.square(x[i] - y[i])))
# 欧氏距离定义的相似度,距离越小相似度越大
XYSimlar = 1 / (1 + XYdistiance)
# 获取相似度和
sum_XYSimlar = sum_XYSimlar + XYSimlar
# 获取两组数据相似度平均值
avg_XYSimlar =1 - sum_XYSimlar / 33 / 33 #等于0时,两者数据一样。值越小,距离越小。
avg_XYSimlar=round(avg_XYSimlar, 3)
-
相似度排序,输出前10个。
关键代码如下:
a=sorted(a)
for i in range(0,10):
print(a[i])
-
采取的距离度量公式及说明
欧几里德距离(Euclidean Distance)最初用于计算欧几里德空间中两个点的距离,假设x,y是n维空间的两个点,它们之间的欧几里德距离是:
可以看出,当n=2时,欧几里德距离就是平面上两个点的距离。当用欧几里德距离表示相似度,一般采用以下公式进行转换:距离越小,相似度越大。
原理:利用欧式距离d定义的相似度S,S=1/(1+d)。
范围:[0,1],值越大,说明d越小,也就是距离越近,则相似度越大。
或:
原理:利用欧式距离d定义的相似度S,S=1-1/(1+d)。
范围:[0,1],值越小,说明d越小,也就是距离越近,则相似度越大。
-
数据文件的中数据的读写方法介绍
用numpy.loadtxt函数将储存数组的文本文件转化为二维数组。
-
程序中数据的组织结构说明
循环结构
1.通过这个循环结构得到源数据的一个32*32的数据块转化的一维的数组arr2
for i in range(i, i+33):
for j in range(j, j+33):
arr1[count]=raw_data[i][j]
count+=1
if j==n_j+32:
j=n_j
arr2=list(arr1.values())
2.通过这个循环结构得到一个数据块与目标数据的相似度
for i in range(0, len(x)):
# 两个数的欧几里得距离
XYdistiance = np.sqrt(np.sum(np.square(x[i] - y[i])))
# 欧氏距离定义的相似度,距离越小相似度越大
XYSimlar = 1 / (1 + XYdistiance)
# 获取相似度和
sum_XYSimlar = sum_XYSimlar + XYSimlar
3.通过这个循环结构得到把二维的目标数据转化为一维的数组
obj = [i for item in obj_data for i in item]
4.通过这个循环结构得到每一个数据块与目标文件的距离及数据块的左上角(第一个数据)在源数据数组中的坐标索引。
for i in range(0, 223):
for j in range(0, 223):
a.append(getArr(raw_data, obj, i, j))
5.排序后,通过这个循环结构得到与目标数据的距离最小的前10个数据块的距离与位置。
a=sorted(a)
for i in range(0,10):
print(a[i])
-
阐述数据块相似算法设计方法
穷举搜索法:穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从众找出那些符合要求的候选解作为问题的解。
在这里我把255*255分成一个一个的32*32数据块(穷尽了所有可能),把32*32的目标数组变成一维数组1089,把32*32数据块的也变成一维数组,在一个一个的计算相似度,把每一个相似度排序(在所有可能中找最接近的10个),输出前10个。
-
算法时间复杂度分析
在该程序中共用了5个双层循环,时间复杂度n2+n2+n2+n2+n2,
n2+n2+n2+n2+n2 ≈ O(N2)
-
实验结果
前10个最相似的数据块信息 | ||
序号 | 位置 | 距离 |
1 | (119,119) | 0 |
2 | (120, 119) | 0.768 |
3 | (118, 119) | 0.773 |
4 | (119, 118) | 0.777 |
5 | (119, 120) | 0.777 |
6 | (120, 118) | 0.796 |
7 | (118, 120) | 0.804 |
8 | (120, 120) | 0.809 |
9 | (118, 118) | 0.812 |
10 | (121, 119) | 0.823 |
注:“位置”指的是搜索到的数据块的左上角(第一个数据)在源数据数组中的坐标索引。