做電子商務網(wǎng)站需要什么軟件愛站網(wǎng)seo查詢
一.算法介紹
核密度估計(Kernel Density Estimation)是一種用于估計數(shù)據(jù)分布的非參數(shù)統(tǒng)計方法。它可以用于多種目的和應用,包括:
- 數(shù)據(jù)可視化:核密度估計可以用來繪制平滑的密度曲線或熱力圖,從而直觀地表示數(shù)據(jù)的分布情況。它可以幫助我們觀察數(shù)據(jù)集中的高密度區(qū)域、低密度區(qū)域以及變化趨勢。
- 異常檢測:通過核密度估計,我們可以識別數(shù)據(jù)中的異常點或離群值。異常點通常表現(xiàn)為低密度區(qū)域或與其他數(shù)據(jù)點明顯不同的區(qū)域。
- 概率密度計算:核密度估計可以用于計算給定數(shù)值的概率密度。通過將新數(shù)據(jù)點帶入核密度估計函數(shù),可以估計出該點在數(shù)據(jù)分布中的密度。
- 模式識別:核密度估計可以用于識別數(shù)據(jù)中的模式或聚類。通過觀察密度最高的區(qū)域,可以推斷數(shù)據(jù)的聚類情況或潛在的模式。
- 預測建模:核密度估計可以用于構(gòu)建概率模型,進而進行預測。例如,在分類問題中,可以使用核密度估計來估計每個類別的概率密度,然后根據(jù)新的數(shù)據(jù)點所屬的密度來進行分類預測。
根據(jù)具體的應用需求,我們可以靈活地使用核密度估計來分析和理解數(shù)據(jù)集的特征和結(jié)構(gòu),可能的用途包括針對社區(qū)規(guī)劃分析房屋密度或犯罪行為,或探索道路或公共設施管線如何影響野生動物棲息地。
每個點位可以設置 weight 字段賦予某些要素比其他要素更大的權(quán)重,該字段還允許使用一個點表示多個觀察對象。例如,一個地址可以表示一棟六單元的公寓,或者在確定總體犯罪率時可賦予某些罪行比其他罪行更大的權(quán)重。
二.算法計算原理
本算法以四次核函數(shù)為基礎,四次核函數(shù)的特點是具有平滑的曲線形狀,具有較寬的窗口,對數(shù)據(jù)點的貢獻在距離較遠時會迅速減小。由于其平滑性和較大的支持范圍,四次核函數(shù)在核密度估計中被廣泛使用。
在核密度估計中,通過將核函數(shù)應用于每個數(shù)據(jù)點,并對所有數(shù)據(jù)點的貢獻進行求和,可以計算出在每個位置上的密度估計值。四次核函數(shù)的結(jié)果可視為在核密度估計中每個位置的密度貢獻權(quán)重。較大的結(jié)果表示該位置的密度較高,而較小或接近零的結(jié)果表示該位置的密度較低。
本算法中主要利用核密度公式計算空間范圍內(nèi)的核密度值,根據(jù)核密度值生成 png 或 jpg 格式的熱力圖,或者將整個空間切割成網(wǎng)格,用網(wǎng)格中心點參與核密度計算生成 geojson 文件,以供進一步空間探索分析。
/*** 計算單個核密度* @param radius 半徑* @param dist 兩點的距離* @param weight 權(quán)重* @return*/public static double computeKernel(double radius, double dist, double weight){return (3 / Math.PI) * weight * Math.pow((1 - Math.pow(dist / radius,2)), 2);}
創(chuàng)新性說明:
- 1.算法會自適應數(shù)據(jù)中的空間點位范圍,此范圍可根據(jù)參數(shù)bufferSize 設置緩沖區(qū)擴展,以獲取數(shù)據(jù)范圍外的點參與計算。
- 2.根據(jù)空間范圍每隔特定步長創(chuàng)建虛擬點位或劃分網(wǎng)格,靈活性較高,步長越小則結(jié)果在地圖分布上的精度越高,步長參數(shù)step(米) 可選,如果沒有設置, 則默認在空間范圍內(nèi)自適應創(chuàng)建一百萬左右虛擬點或網(wǎng)格。
- 3.采用多線程的方式進行核密度計算,速度更快。
- 4.可將結(jié)果值進行歸一化處理,核密度計算出來的結(jié)果值主要用于觀察數(shù)據(jù)分布,但是各個結(jié)果值之間相差范圍較大,不易觀察數(shù)據(jù)分布,歸一化后能更清晰觀察不同區(qū)域間的分布情況。
- 5.可根據(jù)核密度值的大小根據(jù)不同需求生成熱力圖或 geojson 文件??稍趃eojson文件上做進一步探索。
三.算法程序
1. 核心流程代碼
從csv中獲取源數(shù)據(jù)點信息, 獲取坐標范圍,如果需要緩沖區(qū), 則設置緩沖區(qū), 獲取步長長度(默認一百萬個像素點或網(wǎng)格),然后根據(jù)核密度信息創(chuàng)建圖片或geojson
// 輸入文件路徑String inputPath ="D:\\測試數(shù)據(jù).csv";// 輸出文件路徑String outPath ="D:\\測試數(shù)據(jù).geojson";// String outPath ="D:\\測試數(shù)據(jù).jpg";// 經(jīng)度字段String lonKey = "lon";// 緯度字段String latKey = "lat";// 權(quán)重字段String weightKey = "";// 影響半徑double radius = 300.0;// 緩沖區(qū)double bufferSize = 0.1;// 生成的網(wǎng)格長度(單位: 米)int step = 0;int type;if (outPath.endsWith("png") || outPath.endsWith("jpg")){type = 0;}else if (outPath.endsWith("geojson")){type = 1;}else {throw new RuntimeException("輸出文件格式只能是 png、jpg 或者 geojson");}// 從csv中獲取源數(shù)據(jù)點信息List<EntryPoint> entryPoints = EntryPoint.formatToEntryPoints(inputPath, lonKey, latKey, weightKey, radius);// 獲取坐標范圍double[] coordsScope = KernelUtils.getCoordsScope(entryPoints);// 如果需要緩沖區(qū), 則設置緩沖區(qū)if (bufferSize != 0){coordsScope = KernelUtils.getBufferScope(coordsScope[0], coordsScope[1], coordsScope[2], coordsScope[3], bufferSize);}// 獲取默認的步長長度, 默認一百萬個像素點或網(wǎng)格if (step ==0){step = KernelUtils.getDefaultSize(coordsScope);}// 根據(jù)核密度信息創(chuàng)建圖片或geojsonkernel(coordsScope, entryPoints, step, radius, type, outPath);
/*** 核密度方法* @param coordsScope 坐標范圍* @param entryPoints 從csv中獲取源數(shù)據(jù)點信息* @param step 步長長度* @param radius 影響半徑* @param type 輸出文件類型*/public static void kernel(double[] coordsScope, List<EntryPoint> entryPoints, int step, double radius, int type, String path){// 獲取網(wǎng)格坐標系的lon, lat的列表List<Double[]> coords = KernelUtils.getKennelPointCoords(coordsScope[0], coordsScope[1],coordsScope[2],coordsScope[3], step);Progress.progress( progress++);int width = coords.get(0).length;int high = coords.get(1).length;if (type == 1){// 生產(chǎn) geojson 網(wǎng)格結(jié)果generatorGridGeojson(coords, entryPoints, width-1, high-1, radius, path, step);}else {// 生產(chǎn)熱力圖圖片generatorThermalMap(coords, entryPoints, width, high, radius, path, step);}}
2.創(chuàng)建面的 geojson 文件
/*** 根據(jù)核密度信息創(chuàng)建面的 geojson 文件* @param coords 虛擬數(shù)據(jù)點經(jīng)緯度列表* @param entryPoints 數(shù)據(jù)點* @param width 橫向點位數(shù)量* @param high 縱向點位數(shù)量* @param radius 影響半徑*/public static void generatorGridGeojson(List<Double[]> coords, List<EntryPoint> entryPoints,int width, int high, double radius, String path, int step){// 獲取所有中心點位的數(shù)據(jù)List<PixelPoint> pixelPoints = KernelUtils.getGridCenters(coords);// 進行核密度計算, 并記錄受到影響的網(wǎng)格信息KernelResult kernelResult = kernelCompute(entryPoints, pixelPoints, width, high, radius);Double[][] matrix = kernelResult.getMatrix();Double max = kernelResult.getMax();Double min = kernelResult.getMin();// 生產(chǎn)面的 geojson 文件writeToFile(KernelUtils.jointGridGeojson(matrix, max, min, coords), path);System.out.println(String.format("計算完成, 生成 geojson 文件, 參與計算網(wǎng)格 %d 個, 受影響網(wǎng)格 %d 個, 相鄰網(wǎng)格間距 %s 米",pixelPoints.size(), KernelUtils.effectiveGrid, step));}
3.熱力圖圖片
/*** 根據(jù)核密度信息創(chuàng)建熱力圖圖片* @param coords 虛擬數(shù)據(jù)點經(jīng)緯度列表* @param entryPoints 數(shù)據(jù)點* @param width 橫向點位數(shù)量* @param high 縱向點位數(shù)量* @param radius 影響半徑*/public static void generatorThermalMap(List<Double[]> coords, List<EntryPoint> entryPoints,int width, int high, double radius, String path, int step){// 獲得所有點位List<PixelPoint> pixelPoints = KernelUtils.spliceKennelPoints(coords);// 進行核密度計算, 并記錄受到影響的網(wǎng)格信息KernelResult kernelResult = kernelCompute(entryPoints, pixelPoints, width, high, radius);Double[][] matrix = kernelResult.getMatrix();Double max = kernelResult.getMax();Double min = kernelResult.getMin();// 生產(chǎn)熱力圖ImageGenerator.generatorImage(matrix, max, min, path);System.out.println(String.format("計算完成, 生成圖片 像素: %d x %d, 相鄰像素點實際代表距離 %s 米", width, high, step));}
4.計算所有點位的核密度
/*** 計算所有點位的核密度* @param entryPoints 數(shù)據(jù)點信息* @param pixelPoints 創(chuàng)建的虛擬像素點* @param radius 影響半徑* @return*/public static KernelResult kernelCompute(List<EntryPoint> entryPoints, List<PixelPoint> pixelPoints, int width, int high, double radius){List<Double> values = new ArrayList<>();double affectLat = KernelUtils.getLatDist(radius);// 記錄受到影響的網(wǎng)格Double[][] matrix = new Double[high][width];// 建立線程池ThreadPoolExecutor threadPool = new ThreadPoolExecutor(30, 30, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(Integer.MAX_VALUE));// 線程等待計數(shù)器CountDownLatch countDownLatch = new CountDownLatch(pixelPoints.size());// 創(chuàng)建鎖, 使計算數(shù)據(jù)具有線程間可見性Lock lock = new ReentrantLock();int stepPosition = pixelPoints.size() / 75;for (int i = 0; i < pixelPoints.size(); i++){PixelPoint pixelPoint = pixelPoints.get(i);Double kennelLon = pixelPoint.getLon();Double kennelLat = pixelPoint.getLat();threadPool.execute(() -> {// 開始計算每個網(wǎng)格受到其他所有點所影響的核密度double kernel = 0.0;for (int j = 0; j < entryPoints.size(); j++){EntryPoint entryPoint = entryPoints.get(j);double lon = entryPoint.getLon();double lat = entryPoint.getLat();if (Math.abs(lon - kennelLon) > entryPoint.getAffectLon() || Math.abs(lat - kennelLat) > affectLat){continue;}// 獲取權(quán)重, 默認為 1.0double weight = 1.0;if (entryPoint.getWeight() != null){weight = entryPoint.getWeight();}// 計算網(wǎng)格中心點與源數(shù)據(jù)點的距離double distance = KernelUtils.getDistance(lon, lat, kennelLon, kennelLat);// 影響半徑大于距離的點直接去掉if (distance <= radius){// 計算每個網(wǎng)格所受影響的核密度kernel += computeKernel(radius, distance, weight);}}lock.lock();// 為中心點實體類賦予核密度的值Double value = 1 / Math.pow(radius, 2) * kernel;matrix[pixelPoint.getI()][pixelPoint.getJ()] = value;values.add(value);lock.unlock();countDownLatch.countDown();if (countDownLatch.getCount() % stepPosition == 0 && progress < 80){Progress.progress(progress++);}});}// 等待所有任務執(zhí)行完畢try {countDownLatch.await();} catch (InterruptedException e) {throw new RuntimeException(e);}// 關(guān)閉線程池threadPool.shutdown();return new KernelResult(matrix, Collections.max(values), Collections.min(values));}
5.可執(zhí)行 jar 包
該程序可打為可執(zhí)行jar包, 文件夾中的: kernel.jar
運行環(huán)境: jdk 1.8
執(zhí)行示例:
java -jar kernel.jar 杭州市超市營業(yè)額.csv 杭州市超市營業(yè)額熱力.jpg 經(jīng)度 緯度 利潤 2000.0 0.1 0
java -jar kernel.jar 杭州市超市營業(yè)額.csv 杭州市超市營業(yè)額分布.geojson 經(jīng)度 緯度 利潤 2000.0 0.1 0
java -jar kernel.jar 測試數(shù)據(jù).csv 測試數(shù)據(jù).jpg lon lat "" 300.0 0.1 0
java -jar kernel.jar 測試數(shù)據(jù).csv 測試數(shù)據(jù).geojson lon lat "" 300.0 0.1 0
參數(shù) | 參數(shù)位置 | 參數(shù)說明 |
---|---|---|
inputPath | 1 | 輸入的csv文件路徑 |
outPath | 2 | 輸出的文件路徑,程序根據(jù)文件后綴選擇生產(chǎn)的文件類型,只允許 jpg、png、geojson 三種文件。 |
lonKey | 3 | 輸入文件中的經(jīng)度字段名 |
latKey | 4 | 輸入文件中的緯度字段名 |
weightKey | 5 | 輸入文件中的權(quán)重字段名,沒有則輸入”” |
radius | 6 | 影響半徑,單位米,影響半徑越長,周圍空間受該數(shù)據(jù)的影響越廣,需根據(jù)不同的輸入數(shù)據(jù)情況調(diào)整 |
bufferSize | 7 | 空間緩沖區(qū),可擴大數(shù)據(jù)空間范圍,一般0.1即可,即擴大 10% 的區(qū)域 |
step | 8 | 空間劃分步長,步長越小則參與計算的空間點數(shù)據(jù)越多,計算量越大,結(jié)果數(shù)據(jù)越精確, 需根據(jù)不同的輸入數(shù)據(jù)情況調(diào)整,當值為0時,程序則適配生成一百萬個點或網(wǎng)格參與計算,注:盡量不要在城市級別范圍設置過低步長 |
四.執(zhí)行結(jié)果展示
熱力圖示例:
平臺分析示例:
杭州市超市營業(yè)額區(qū)域性分析-熱力圖:
杭州市超市營業(yè)額區(qū)域性分析-平臺分析:
五、應用場景
-
金融風險評估:核密度算法可以用于評估某種投資方式的風險程度。將歷史數(shù)據(jù)輸入核密度估計器中,可以得出該投資方式在不同風險水平下的收益概率密度分布。這有助于金融機構(gòu)更好地了解風險和收益之間的平衡。
-
生態(tài)學:核密度算法可用于研究動植物的棲息地和遷徙模式。將動植物的觀察數(shù)據(jù)輸入核密度估計器中,可以得出它們在不同地點出現(xiàn)的概率密度分布,幫助科學家更好地了解動植物的棲息地范圍和活動規(guī)律。
-
交通流量預測:核密度算法可以用于預測道路上的交通流量。將歷史交通流量數(shù)據(jù)輸入核密度估計器中,可以得出在不同時間段內(nèi)和不同位置上的交通流量概率密度分布。這有助于交通管理人員更好地規(guī)劃道路、優(yōu)化路線和管理交通擁堵。
-
模式識別:核密度算法可以使用于人臉識別、圖像處理等領域。將輸入數(shù)據(jù)的特征值輸入核密度估計器中,可以得出不同特征值下相應數(shù)據(jù)的概率密度分布。這可用于識別圖像中不同物體的特征值,例如人臉的輪廓和眼睛的位置,從而實現(xiàn)自動化識別。