當前位置:首頁 » 編程語言 » kdtreepython

kdtreepython

發布時間: 2022-11-08 11:10:58

python里的kdtree能不能進行漢明距離的搜索

KDTree也是一種特殊的二叉樹,同二叉搜索樹類似,也是可以邊加入新節點,邊維護樹結構的。
建議用numpy

通過python3中numpy庫實現漢明距離(Hamming distance)的計算
漢明距離的定義:兩個等長字元串s1 與s2 之間的漢明距離定義為將其中一個變為另外一個所需要做的最小替換次數。例如字元串―1111‖與―1001‖之間的漢明距離為2。
應用:信息編碼(為了增強容錯性,應使得編碼間的最小漢明距離盡可能大)。
程序實現:
通過對應向量(或矩陣)相減,結果中元素中非零元素個數即為漢明距離
例如:
vector1 = mat([1,1,0,1,0,1,0,0,1])
vector2 = mat([0,1,1,0,0,0,1,1,1])
vector3 = vector1-vector2= [[ 1 0 -1 1 0 1 -1 -1 0]]
通過函數nonzero(vector3)以矩陣的形式返回輸入值中非零元素的信息如下:
(matrix([[0, 0, 0, 0, 0, 0]], dtype=int32), matrix([[0, 2, 3, 5, 6, 7]], dtype=int32))
再通過shape函數是讀取返回值中矩陣的長度,即為漢明距離的長度。
代碼如下:
from numpy import *
vector1 = mat([1,1,0,1,0,1,0,0,1])
vector2 = mat([0,1,1,0,0,0,1,1,1])
vector3 = vector1-vector2
print("vector3 = vector1-vector2",vector3)
smstr = nonzero(vector1-vector2);
print (smstr)
print (shape(smstr[0])[1])
程序運行結果如下:
vector3 = vector1-vector2 [[ 1 0 -1 1 0 1 -1 -1 0]]
(matrix([[0, 0, 0, 0, 0, 0]], dtype=int32), matrix([[0, 2, 3, 5, 6, 7]], dtype=int32))
6

Ⅱ PyOD主要演算法(KNN、IForest 和 MCD)的原理及使用

https://pyod.readthedocs.io/en/latest/pyod.models.html

Python Outlier Detection(PyOD)是當下最流行的Python異常檢測工具庫(toolkit)。該工具庫的主要亮點包括:

對於特徵空間中的一個樣本,如果與之最相似的(即特徵空間中距離最近的)k個樣本中的大多數都屬於某一類別,則該樣本的分類結果也是這個類別。

https://www.cnblogs.com/lesleysbw/p/6074662.html

① 什麼叫做KD_tree

K:K鄰近查詢中的k;D:空間是D維空間(Demension)tree:二叉樹

② 建樹過程

K-D tree的建立就是分裂空間的過程

首先,我們對整個區間 [1 , 15] 建樹:先計算區間中所有點在第一維(也就是 x 坐標)上的方差:
平均值 : ave_1 =5.4
方差 : varance_1 =9.04
再計算區間中所有點在第二維(也就是 y 坐標)上的方差:
平均值:ave_2 =6.8
方差:varance_2 =10.96
明顯看見,varance_2 > varance_1 ,那麼我們在本次建樹中, 分裂方式 :split_method =2 , 再將所有的點按照第2維的大小 從小到大排序 ,得到了新的點的一個排列:
(4,2) (1,4) (5,8) (7,9) (10,11)
取中間的點作為分裂點 sorted_mid =(5,8)作為根節點,再把區間 [1 , 2] 建成左子樹 , [4 , 5] 建成右子樹,此時,直線 : y = 8 將平面分裂成了兩半,前面一半給左兒子,後面一半給了右兒子,如圖:

建左子樹 [1, 3] 的時候可以發現,這時候 第一維的方差大 ,分裂方式就是1 ,把區間 [ 1, 2 ] 中的點按照 第一維 的大小,從小到大排序 ,取 中間點(1,4) 根節點,再以區間 [ 2, 2] 建立右子樹 得到節點 (4,2)

建右子樹 [4 , 5] 的時候可以發現,這時還是第一維的方差大, 於是,我們便得到了這樣的一顆二叉樹 也就是 K-D tree,它把平面分成了如下的小平面, 使得每個小平面中最多有一個點

③ 查詢過程:
查詢,其實相當於我們要將一個點「添加」到已經建好的 K-D tree 中,但並不是真的添加進去,只是找到他應該 處於的子空間 即可,所以查詢就顯得簡單的。
每次在一個區間中查詢的時候,先看這個區間的 分裂方式 是什麼,也就是說,先看這個區間是按照哪一維來分裂的,這樣如果這個點對應的那一維上面的值比根節點的小,就在根節點的左子樹上進行查詢操作,如果是大的話,就在右子樹上進查詢操作。
每次回溯到了根節點(也就是說,對他的一個子樹的查找已經完成了)的時候,判斷一下,以該點為圓心,目前 找到的最小距離為半徑 ,看是否和分裂區間的那一維所構成的平面相交,要是相交的話,最近點可能還在另一個子樹上,所以還要再查詢另一個子樹,同時,還要看能否用根節點到該點的距離來更新我們的最近距離。為什麼是這樣的,我們可以用一幅圖來說明:

https://github.com/YinghongZhang/BallTree-MIPS

① 原理
為了改進KDtree的二叉樹樹形結構,並且沿著笛卡爾坐標進行劃分的低效率,ball tree將在一系列嵌套的超球體上分割數據。也就是說: 使用超球面而不是超矩形劃分區域 。雖然在構建數據結構的花費上大過於KDtree,但是在 高維 甚至很高維的數據上都表現的很高效。
球樹遞歸地將數據劃分為 由質心C和半徑r定義的節點 ,使得節點中的每個點都位於由r和C定義的超球內。通過使用三角不等式來減少鄰居搜索的候選點數量。

② 建樹過程
選擇一個距離當前圓心最遠的觀測點A,和距離A最遠的觀測點B,將圓中所有離這兩個點最近的觀測點都賦給這兩個簇的中心,然後計算每一個簇的中心點和包含所有其所屬觀測點的最小半徑。對包含n個觀測點的超圓進行分割,只需要線性的時間。

③ 查詢
使用ball tree時,先自上而下找到包含target的葉子結點(c, r),從此結點中找到離它最近的觀測點。這個距離就是 最近鄰的距離的上界 。檢查它的 兄弟結點 中是否包含比這個上界更小的觀測點。方法是: 如果目標點距離兄弟結點的圓心的距離d > 兄弟節點所在的圓半徑R + 前面的上界r,則這個兄弟結點不可能包含所要的觀測點 。否則,檢查這個兄弟結點是否包含符合條件的觀測點。

用一個隨機超平面來切割數據空間, 直到每個子空間裡面只有一個數據點為止。切割次數的多少可用來區分異常。

https://www.jianshu.com/p/5af3c66e0410

iForest 由t個iTree孤立樹組成,每個iTree是一個二叉樹,其實現步驟如下:

可以看到d最有可能是異常,因為其最早就被孤立(isolated)了。

獲得t個iTree之後,iForest 訓練就結束,然後我們可以用生成的iForest來評估測試數據了。對於一個訓練數據x,我們令其遍歷每一棵iTree,然後計算x最終落在每個樹第幾層(x在樹的高度),得到x在每棵樹的高度平均值。獲得每個測試數據的average path length後,我們可以設置一個閾值,低於此閾值的測試數據即為異常。
IForest具有線性時間復雜度。
IForest不適用於特別高維的數據。

最小協方差行列式(Minimum Covariance Determinant)

https://max.book118.com/html/2017/1217/144650709.shtm

論文《Minimum covariance determinant and extensions》中有更詳細描述。

論文《A Fast Algorithm for the Minimum Covariance Determinant Estimator》有更詳細描述。

Ⅲ python 如何畫出KD數

簡單的KNN演算法在為每個數據點預測類別時都需要遍歷整個訓練數據集來求解距離,這樣的做法在訓練數據集特別大的時候並不高效,一種改進的方法就是使用kd樹來存儲訓練數據集,這樣可以使KNN分類器更高效。
KD樹的主要思想跟二叉樹類似,我們先來回憶一下二叉樹的結構,二叉樹中每個節點可以看成是一個數,當前節點總是比左子樹中每個節點大,比右子樹中每個節點小。而KD樹中每個節點是一個向量(也可能是多個向量),和二叉樹總是按照數的大小劃分不同的是,KD樹每層需要選定向量中的某一維,然後根據這一維按左小右大的方式劃分數據。在構建KD樹時,關鍵需要解決2個問題:(1)選擇向量的哪一維進行劃分(2)如何劃分數據。第一個問題簡單的解決方法可以是選擇隨機選擇某一維或按順序選擇,但是更好的方法應該是在數據比較分散的那一維進行劃分(分散的程度可以根據方差來衡量)。好的劃分方法可以使構建的樹比較平衡,可以每次選擇中位數來進行劃分,這樣問題2也得到了解決。下面是建立KD樹的Python代碼:
def build_tree(data, dim, depth):
"""
建立KD樹

Parameters
----------
data:numpy.array
需要建樹的數據集
dim:int
數據集特徵的維數
depth:int
當前樹的深度
Returns
-------
tree_node:tree_node namedtuple
樹的跟節點
"""
size = data.shape[0]
if size == 0:
return None
# 確定本層劃分參照的特徵
split_dim = depth % dim
mid = size / 2
# 按照參照的特徵劃分數據集
r_indx = np.argpartition(data[:, split_dim], mid)
data = data[r_indx, :]
left = data[0: mid]
right = data[mid + 1: size]
mid_data = data[mid]
# 分別遞歸建立左右子樹
left = build_tree(left, dim, depth + 1)
right = build_tree(right, dim, depth + 1)
# 返回樹的根節點
return Tree_Node(left=left,
right=right,
data=mid_data,
split_dim=split_dim)


對於一個新來的數據點x,我們需要查找KD樹中距離它最近的節點。KD樹的查找演算法還是和二叉樹查找的演算法類似,但是因為KD樹每次是按照某一特定的維來劃分,所以當從跟節點沿著邊查找到葉節點時候並不能保證當前的葉節點就離x最近,我們還需要回溯並在每個父節點上判斷另一個未查找的子樹是否有可能存在離x更近的點(如何確定的方法我們可以思考二維的時候,以x為原點,當前最小的距離為半徑畫園,看是否與劃分的直線相交,相交則另一個子樹中可能存在更近的點),如果存在就進入子樹查找。
當我們需要查找K個距離x最近的節點時,我們只需要維護一個長度為K的優先隊列保持當前距離x最近的K個點。在回溯時,每次都使用第K短距離來判斷另一個子節點中是否存在更近的節點即可。下面是具體實現的python代碼:
def search_n(cur_node, data, queue, k):
"""
查找K近鄰,最後queue中的k各值就是k近鄰

Parameters
----------
cur_node:tree_node namedtuple
當前樹的跟節點
data:numpy.array
數據
queue:Queue.PriorityQueue
記錄當前k個近鄰,距離大的先輸出
k:int
查找的近鄰個數
"""
# 當前節點為空,直接返回上層節點
if cur_node is None:
return None
if type(data) is not np.array:
data = np.asarray(data)
cur_data = cur_node.data
# 得到左右子節點
left = cur_node.left
right = cur_node.right
# 計算當前節點與數據點的距離
distance = np.sum((data - cur_data) ** 2) ** .5
cur_split_dim = cur_node.split_dim
flag = False # 標記在回溯時是否需要進入另一個子樹查找
# 根據參照的特徵來判斷是先進入左子樹還是右子樹
if data[cur_split_dim] > cur_data[cur_split_dim]:
tmp = right
right = left
left = tmp
# 進入子樹查找
search_n(left, data, queue, k)
# 下面是回溯過程
# 當隊列中沒有k個近鄰時,直接將當前節點入隊,並進入另一個子樹開始查找
if len(queue) < k:

neg_distance = -1 * distance
heapq.heappush(queue, (neg_distance, cur_node))
flag = True
else:
# 得到當前距離數據點第K遠的節點
top_neg_distance, top_node = heapq.heappop(queue)
# 如果當前節點與數據點的距離更小,則更新隊列(當前節點入隊,原第k遠的節點出隊)
if - 1 * top_neg_distance > distance:
top_neg_distance, top_node = -1 * distance, cur_node
heapq.heappush(queue, (top_neg_distance, top_node))
# 判斷另一個子樹內是否可能存在跟數據點的距離比當前第K遠的距離更小的節點
top_neg_distance, top_node = heapq.heappop(queue)
if abs(data[cur_split_dim] - cur_data[cur_split_dim]) < -1 * top_neg_distance:
flag = True
heapq.heappush(queue, (top_neg_distance, top_node))
# 進入另一個子樹搜索
if flag:
search_n(right, data, queue, k)525354555657

以上就是KD樹的Python實踐的全部內容,由於本人剛接觸python不久,可能實現上並不優雅,也可能在演算法理解上存在偏差,如果有任何的錯誤或不足,希望各位賜教。

Ⅳ python如何在眾多的點中找到與特定點最近的點的演算法

首先目測一下查詢大概不止一次所以前面那些統統乘個Q就大爆炸吧。
平民的做法寫個kdtree基本sqrt n復雜度對付10w的數據量應該輕松愉快,動態的話套個替罪羊。
泥垢無聊的話動態v圖歡迎入坑 傳聞是logn的我沒寫過不知道會不會比上面的慢。
啊找到了我記得這個大輪子應該可以很簡單(不如手寫)的解決你的問題
PCL - Point Cloud Library (PCL)
-

單純的替罪羊套kdt放到這種場合可能不大合適……畢竟修改一次可能鎖死整個子樹……(當然可以不用替罪羊,緩存sqrt n個修改,然後每sqrt n個修改暴力重構整個樹,重構完成之前就先用原來的,然後再加上各種奇怪的優化……。)
然後再YY一下,我個人覺得他們可能是這樣乾的,首先把地圖切成一塊一塊的每塊足夠小。然後隨便YY一下按照每個地方人數的多少,取一個合適的am^2范圍內最多有x人,然後只要這個x夠小,查詢的時候只查詢當前用戶所在的區塊和周圍的幾個區塊就好了,然後你就可以用輪子哥那樣的sql查詢啦~
如果還是有問題要麼加伺服器,或者最不濟還可以對這個區塊再維護kdtree。而且這樣修改起來還方便。
至於用戶周圍都沒有人,最近的有人區塊在幾十公里外…

Ⅳ 如何設計好詞袋模型的類類型

如何設計好詞袋模型的類類型
回顧過去自己寫過的一些詞袋模型,比如 BoW圖像檢索Python實戰 、 圖像檢索(CBIR)三劍客之BoF、VLAD、FV 以及Bag of Words cpp實現,這些寫出來的要麼只是助於自己理解詞袋模型的有關理論,要麼也只是面向實驗的一些驗證,或者更直接點可以說只是些小玩具擺了。
在我2016年的計劃列表裡,存放著一條由2015年拖過來的目標,就是寫出一個可以面向商業級別的詞袋模型,這條計劃伴隨著成功將VLfeat的一些c介面打通而變成了可能,並且在過去的大半年裡,自己也一直留意在具體編寫的時候選用哪些庫比較合適的問題。機緣巧合,這一段時間又重新開始造起了輪子,並有了初步的成功,所以在此梳理總結一下。在談怎樣設計一個詞袋模型的類類型之前,先談談庫的選用問題。
選取合適的庫
在具體編寫一個面向應用級別的詞袋模型的時候,大概會經歷這么幾個步驟:SIFT特徵抽取,特徵采樣,聚類,構建KD樹,統計詞頻,計算詞頻權重,計算詞頻直方圖,保存數據。這8個步驟在具體實現的時候,會設計到一些庫的選取問題,下面對其進行細談。
1) SIFT特徵抽取提取選用哪個庫?
提取SIFT的庫有很多,主要有以下幾個大家用得比較多:
Lowe的 SIFT ,效果只提供SIFT的二進制可執行文件,棄用;
Robwhess的 OpenSIFT ,開源,效果也還不錯,需要一些別的依賴庫,不再更新,棄用;
OpenCV的SIFT,這個當然在使用上是最方便的,文檔全,不依賴別的庫,但SIFT的實現效果並不是很好,棄用;
VLfeat里的 SIFT ,SIFT的實現效果是比較好的,缺點是c介面文檔不怎麼全,網上提供的資料也比較少,但多讀讀它的C源碼,還是可以搞定的,而且在不用依賴其他的庫,所以選擇這個庫來提取SIFT還是很好的,在實際提取的時候,我選用的是 covdet 函數來提取SIFT,它是一個功能更強大的提取co-variant特徵提取器。
在去年的時候,基本弄清了VLfeat中的一些函數的C介面調用方式,covdet這個函數通過閱讀寫給matlab的介面源碼轉成的C,對比matlab提取的結果和自己轉成C之後提取的結果,兩者完全一致。
2) 矩陣運算庫的選取

雖然使用矩陣操作並不是必須的,除了OpenCV的矩陣,還有可能引入其他的矩陣運算庫,這些矩陣的引入會給後面的實現帶來巨大的方便,比如聚類,KD樹的構建以及後面詞頻統計等。作為運算的基礎庫,在矩陣庫的選擇上主要有下面幾個用得比較多:

Eigen ,使用的只需要把頭文件包含進工程里即可,提供了多個平台的版本,比如可以運行於安卓上,矩陣運算操作還是比較方便的,更新得比較快,不過在PC平台上開發,我比較傾向於使用下面要說的Armadillo。
Armadillo ,這個庫是我非常喜歡的矩陣運算庫,此矩陣庫在使用語法上Matlabjie借鑒了Matlab的語法使用習慣,所以熟悉Matlab的開發者在使用此庫的時候會覺得非常的舒服,並且有名的MLPack是建立在它的基礎之上,另外它的矩陣運算效率也是非常高的,使用的時候同Eigen一樣只需要包含頭文件目錄即可,最新版本中添加了KMeans聚類。因而,基於以上這些優點,在實現詞袋模型的時候,對於矩陣運算庫的選取,選擇這個無疑是最優的。
選用矩陣庫雖然能極大的方便我們的程序編寫,但是會涉及到數據類型的轉換,比如STL的vector存儲的數據要轉成Armadillo的矩陣進行運算,如果數據頻繁的進行類型的轉換,必然會降低程序的運行效率,因而在程序的編寫中,不必要轉換的盡量避免轉換。

3) 多線程並行處理

為了使程序的SIFT特徵提取、KMeans聚類、統計詞頻等過程支持並行處理,在選擇並行計算庫的時候,有兩種選擇,一種是採用OpenMP,另一種是選擇MPI。OpenMP是採用的是內存共享的方式,只需要對原程序進行小幅調整即可實現並行處理,並且語法易讀已寫;MPI需要對原來的程序進行大幅重構,寫出來的代碼也不是很好讀。所以,在多線程並處計算庫選擇這塊,選擇OpenMP是比較好的。

詞袋模型的類類型設計

終於可以講核心的了,這一部分講講在編寫程序的時候自己對詞袋模型的類類型設計的一點心得。先上自己寫的詞袋模型的類類型,設計了兩個類,一個是 SIFT特徵提取的類類型 ,另一個是 詞袋模型的類類型 。先談談 SIFT特徵提取的類類型 :

class siftDesctor{
public:
siftDesctor(){};
std::string imageName;
std::vector<std::vector<float>> frame;
std::vector<std::vector<float>> desctor;
void covdet_keypoints_and_descriptors(cv::Mat &img, std::vector<std::vector<float>> &frames, std::vector<std::vector<float>> &desctor, bool rooSIFT, bool verbose);
std::vector<float> rootsift(std::vector<float> &dst);

void Serialize(std::ofstream &outfile) const {
std::string tmpImageName = imageName;
int strSize = (int)imageName.size();
outfile.write((char *)&strSize, sizeof(int));
outfile.write((char *)&tmpImageName[0], sizeof(char)*strSize); // 寫入文件名

int descSize = (int)desctor.size();
outfile.write((char *)&descSize, sizeof(int));

// 寫入sift特徵
for(int i = 0; i < descSize; i++ ){
outfile.write((char *)&(desctor[i][0]), sizeof(float) * 128);
outfile.write((char *)&(frame[i][0]), sizeof(float) * 6);
}

}

static siftDesctor Deserialize(std::ifstream &ifs) {
siftDesctor siftDesc;
int strSize = 0;
ifs.read((char *)&strSize, sizeof(int)); // 寫入文件名
siftDesc.imageName = "";
siftDesc.imageName.resize(strSize);
ifs.read((char *)&(siftDesc.imageName[0]), sizeof(char)*strSize); // 讀入文件名

int descSize = 0;
ifs.read((char *)&descSize, sizeof(int));

// 讀入sift特徵和frame
for(int i = 0; i < descSize; i++ ){
std::vector<float> tmpDesc(128);
ifs.read((char *)&(tmpDesc[0]), sizeof(float) * 128);
siftDesc.desctor.push_back(tmpDesc);

std::vector<float> tmpFrame(6);
ifs.read((char *)&(tmpFrame[0]), sizeof(float) * 6);
siftDesc.frame.push_back(tmpFrame);
}

return siftDesc;
}

};
在設計SIFT特徵提取的類類型的時候,對於每一幅圖像,提取SIFT特徵之後,由於需要保存圖像名、128維的SIFT特徵以及6維的frame,因為 imageName 、 desctor 和 frame 這三個成員是必須的,這里說一下對於 imageName 這個成員,在最後保存方式文件名的時候,更合理的方式是不應該帶入文件所在目錄路徑的,因為最終寫入的數據有可能轉移到別的計算機上,帶入路徑不便於共享後使用者對數據的處理,這個地方我在剛開始設計的時候有欠考慮。另外,剛開始在設計 covdet_keypoints_and_descriptors() 方法的時候,是在方法里讀入圖片然後在提取特徵的,當時想得是想讓這樣一個特徵提取器更加的方便使用(只需要傳入圖像待路徑的文件名就可以處理),但後來發現其實根本沒必要這么設計這個方法,這種蹩腳的方式使得後面在顯示結果的時候,你需要再次讀入圖片,降低了程序的執行效率,因而改成了現在的這種傳入已讀入數據的方式。

上面除了三個重要的成員變數,兩個序列化和反序列化的方法是極其重要的,序列化的目的使得上面三個重要的成員變數得以保存,這樣可以避免當我們想再次聚類時又要提取特徵的尷尬;反序列化使得我們可以讀取保存的數據,因而,三個成員變數加兩個方法都是必不可少的。

再談 詞袋模型的類類型 ,先看類定義:

class bowModel {
public:
bowModel(){};
bowModel(int _numWords,std::vector<siftDesctor> _imgFeatures, std::vector<std::vector<int>> _words):numWords(_numWords),imgFeatures(_imgFeatures),words(_words){};

int numNeighbors = 1;
int numWords;
std::vector<siftDesctor> imgFeatures;
std::vector<std::vector<int>> words;
cv::Mat centroids_opencvMat;

cv::flann::Index opencv_buildKDTree(cv::Mat ¢roids_opencvMat);

void Serialize(std::ofstream &outfile) const {
int imgFeatsSize = (int)imgFeatures.size();
outfile.write((char *)&imgFeatsSize, sizeof(int));
// 寫入imgFeatures和words
for(int i = 0; i < imgFeatsSize; i++ ){
imgFeatures[i].Serialize(outfile);
outfile.write((char *)&(words[i][0]), sizeof(int) * imgFeatures[i].desctor.size());
}

}

static bowModel Deserialize(std::ifstream &ifs) {
bowModel BoW;
int imgFeatsSize;
ifs.read((char *)&imgFeatsSize, sizeof(int));

BoW.words.resize(imgFeatsSize);

for (int i = 0; i < imgFeatsSize; i++) {
// 讀入imgFeatures
auto siftDesc = siftDesctor::Deserialize(ifs);
BoW.imgFeatures.push_back(siftDesc);
// 讀入words
BoW.words[i].resize(siftDesc.desctor.size());
ifs.read((char *)&(BoW.words[i][0]), sizeof(int) * siftDesc.desctor.size());
}
return BoW;
}

};
上面最重要的有三個東西,一是成員 std::vector<siftDesctor> imgFeatures ,另外是序列化和反序列化方法。對於每一個圖片提取的特徵,將 imageName 、 desctor 和 frame 通過實例化一個siftDesctor將其保存起來,這樣我們將所有圖片的siftDesctor實例用STL的vector保存下來,在序列化的時候,對每一個實例通過調用 SIFT特徵提取的類類型 中定義的序列化方法將其保存下來,讀取數據的時候,其過程基本就是原來的一個擬過程。通過這樣設計這樣兩個 SIFT特徵提取的類類型 和 詞袋模型的類類型 ,在數據讀寫的時候,通過內外兩重循環,內部循環完成一個實例的數據讀寫,外部循環完成所有圖片實例的讀寫,使得我們可以比較優雅地完成圖片的特徵提取、數據保存以及讀寫。

對於數據讀寫,做過一番調研,一種是通過HDF5的方式,一種是通過BOOST庫。HDF5很適合大數據量的保存,而且讀寫高效,但在C++里,寫起來沒有在Python里使用HDF5方便,BOOST也查閱過相應的資料,寫起來也比較繁雜,所以最後選擇了只用fstream來進行數據讀寫保存了,測了一下,數據讀寫還是比較高效的,所以暫且採用這種方案。

熱點內容
最新款的電腦高配置是什麼樣的 發布:2025-01-12 01:44:08 瀏覽:823
編程手舞蹈 發布:2025-01-12 01:36:18 瀏覽:958
阿里雲伺服器要備案嗎 發布:2025-01-12 01:36:06 瀏覽:94
資料庫應用與信息管理 發布:2025-01-12 01:26:06 瀏覽:269
esxi管理存儲伺服器 發布:2025-01-12 01:25:59 瀏覽:767
在烏班圖搭建web伺服器 發布:2025-01-12 01:25:24 瀏覽:390
浙江省開票軟體升級版伺服器地址 發布:2025-01-12 01:15:57 瀏覽:203
蘋果電腦怎麼進入電腦伺服器 發布:2025-01-12 01:08:49 瀏覽:731
安卓平板怎麼設置隔空刷抖音 發布:2025-01-12 01:08:12 瀏覽:392
手機設備存儲是什麼 發布:2025-01-12 01:03:45 瀏覽:906