使用Java调用Apache commons-text求解字符串相似性实战

news2024/9/21 20:32:48

目录

前言

一、字符串距离的几种计算方法

1、Levenshtein 距离

2、Overlap Coefficient计算

3、Q-gram Matching

4、余弦相似性计算

二、基于余弦相似性的基地名称对比

1、加载百科中的基地信息列表

2、设置忽略词列表 

3、将数据库地名和Excel进行对比

三、总结


前言

        在之前的一篇漂亮国的全球的基地博客中,我们曾经对漂亮国的全球基地进行了一些梳理。博文中使用的数据来源,重点是参考以为博主分享的KML的数据,同时针对其国内的基地部署信息,我们从互联网百科的数据中搜寻到一些。其实拿到这两份数据的时候,是存在一些问题的,比如,KML的数据它的基地名称都是英文的,而在互联网上公开的数据中,良莠不齐,有的是中文的,有的是英文,有的中英文都有,而且可能还存在同样的英文,它的描述不一样的情况,比如下面的场景:

XXX Air Base 空军基地 

XXX Air Station 航空站

        可能不同的信息来源,其主要的名称对应的真实位置表示的是同一个。再比如漂亮国驻小日子的基地列表。

Idesuna Jima Air Range 

FAC 6078 出砂岛炸射练习场 Idesuna Jima Range 训练 冲绳渡名喜村

        上面一行是从KML中解析出来的基地名称,而下面是从某百科中得到的数据。 当我们将句子的影响词(当出现在军事基地的领域中的某些特定词,如Air、Base、Station、Range等这些词去掉后)其主要的地点就是同一个,通过对比主要关键词的相似性,为我们实现将两个地名进行对齐,甚至可以设定一个阈值,当两个字符串的相似性超过多少(比如超过90%)就认为这是同一个地点,从而可以实现将基地的中文名和所驻地的国家、城市等信息进行一一匹配。从而减少人工对比的工作。

        随着现代技术的快速发展,文本相似度计算有很多种方法,甚至可以用大数据、自然语言处理还可以结合人工智能的方法来实现精确的文本相似性判断。但是本文不想实现那么复杂的架构,只想简单快速的解决两个地址的快速匹配问题。博客以Java编程为例,讲解了在Java中求解两个字符串的几种方法。通过求解编辑距离、Q-gram Matching、还有余弦相似性计算,通过对比不同的方法,调用Apache 的Common-text中基于余弦的字符相似性得到了比较比错的结果。算法比较简单,主要想说明两个字符串的不同距离的计算,对于更复杂的模型,大家感兴趣的可以搜索相关的科研论文来学习。

一、字符串距离的几种计算方法

        为了比较字符的相似性,我们通过通过对比距离(把两个字符串的距离计算出来,当然这个距离的计算是有讲究的,具体的算法就是我们说的距离算法,不同的距离算法,得到的值是不一样的)。因此这里我们打算讲将在Java当中,有哪些距离的计算方法以及如何编写相应的代码。

1、Levenshtein 距离

        计算将一个字符串转换为另一个字符串所需的最少单字符编辑操作(插入、删除或替换)的数量。在下面这个示例中,levenshteinDistance方法使用动态规划来计算两个字符串之间的Levenshtein Distance。calculateNormalizedLevenshteinDistance方法则使用这个距离和两个字符串长度的最大值来计算标准化的Levenshtein Distance。 main方法中给出了两个示例字符串s1和s2,并调用calculateNormalizedLevenshteinDistance方法来计算并打印它们的Normalized Levenshtein Distance。根据这个得分,你可以设定一个阈值来判断两个字符串是否相似。例如,如果Normalized Levenshtein Distance小于0.2(即80%的字符是匹配的),你可以认为这两个字符串是相似的。这个阈值可以根据你的具体需求进行调整。
 

package com.yelang.project;

public class NormalizedLevenshteinDistance {
	// 计算Levenshtein Distance
    public static int levenshteinDistance(String s1, String s2) {
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];
        for (int i = 0; i <= s1.length(); i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= s2.length(); j++) {
            dp[0][j] = j;
        }
        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                int cost = (s1.charAt(i - 1) == s2.charAt(j - 1)) ? 0 : 1;
                dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + cost);
            }
        }
        return dp[s1.length()][s2.length()];
    }
    // 计算Normalized Levenshtein Distance
    public static double calculateNormalizedLevenshteinDistance(String s1, String s2) {
        int distance = levenshteinDistance(s1, s2);
        int maxLength = Math.max(s1.length(), s2.length());
        return (double) distance / maxLength;
    }
    public static void main(String[] args) {
        String s1 = "Camp Humphreys";
        String s2 = "United States Army Garrison-Humphreys";
        double normalizedDistance = calculateNormalizedLevenshteinDistance(s1, s2);
        System.out.println("Normalized Levenshtein Distance: " + normalizedDistance);
    }
}

        运行上述程序后,得到的结果如下,表示两个字符串的相似度是0.67:

Normalized Levenshtein Distance: 0.6756756756756757

2、Overlap Coefficient计算

        Overlap Coefficient是通过计算两个字符串的最长公共子序列的长度来求两者的相似度的。这种算法有弊有利,在主要的关键词不同而基地的信息完一致的情况下,比如xxx air base 和xx1 air base,通过计算得到的结果一定及其相似,因为这两个字符串的最长公共序列很长啊,计算机看起来就像是完全一致的。

package com.yelang.project;
public class OverlapCoefficient {
	// 计算最长公共子序列的长度
    public static int longestCommonSubsequence(String s1, String s2) {
        int len1 = s1.length();
        int len2 = s2.length();
        int[][] dp = new int[len1 + 1][len2 + 1];
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[len1][len2];
    }
    // 计算Overlap Coefficient
    public static double calculateOverlapCoefficient(String s1, String s2) {
        int lcsLength = longestCommonSubsequence(s1, s2);
        int minLength = Math.min(s1.length(), s2.length());
        return (double) lcsLength / minLength;
    }
    public static void main(String[] args) {
        String s1 = "Camp Humphreys";
        String s2 = "United States Army Garrison-Humphreys";
        double overlapCoefficient = calculateOverlapCoefficient(s1, s2);
        System.out.println("Overlap Coefficient: " + overlapCoefficient);
    }
}

        运行以上程序后,得到的结果是:

Overlap Coefficient: 0.8571428571428571

        它判定是85%的相似度,貌似看起来比第一种距离很接近真相,你换个词去测试就发现,这种算法其实很蠢。

3、Q-gram Matching

        Q-gram Matching是一种基于子串的字符串相似度计算方法,其中Q表示子串的长度。对于两个字符串,计算它们共有的Q-gram(长度为Q的连续子串)的数量,然后将这个数量除以两个字符串中Q-gram数量较少的那个, 得到相似度的比例。下面给出它的Java实现:

package com.yelang.project;
import java.util.HashSet;
import java.util.Set;
public class QGramMatching {
	/**
	 * 在这个示例中,calculateQGrams方法接受一个字符串和一个整数Q,然后返回该字符串所有可能的Q-gram的集合。calculateQGramSimilarity方法接受两个字符串和一个整数Q,计算它们的Q-gram集合,并找出共有的Q-gram数量,然后计算相似度。main方法中给出了两个示例字符串s1和s2,以及Q-gram的长度Q,并调用calculateQGramSimilarity方法来计算并打印它们的Q-gram相似度。
	请注意,Q-gram的长度Q是一个参数,可以根据具体应用场景进行调整。较短的Q值可以捕捉到更细粒度的相似性,而较长的Q值则可以捕捉到更宽泛的相似性。此外,相似度的阈值可以根据实际需求设定,以判断两个字符串是否相似。
	 */
	// 计算字符串的Q-gram集合
    public static Set<String> calculateQGrams(String s, int q) {
        Set<String> qGrams = new HashSet<>();
        for (int i = 0; i <= s.length() - q; i++) {
            qGrams.add(s.substring(i, i + q));
        }
        return qGrams;
    }
    // 计算两个字符串的Q-gram相似度
    public static double calculateQGramSimilarity(String s1, String s2, int q) {
        Set<String> qGrams1 = calculateQGrams(s1, q);
        Set<String> qGrams2 = calculateQGrams(s2, q);
        // 计算两个集合的交集
        Set<String> intersection = new HashSet<>(qGrams1);
        intersection.retainAll(qGrams2);
        // 计算相似度
        double similarity = intersection.size() / (double) Math.min(qGrams1.size(), qGrams2.size());
        return similarity;
    }
    public static void main(String[] args) {
        String s1 = "Camp Humphreys";
        String s2 = "United States Army Garrison-Humphreys";
        // Misawa Air Range<==>Misawa Air Base:similar = 0.9058216273156766
        // Gun Training Area<==>Tsuken Jima Training Area:similar = 0.9202830114233174
        int q = 3; // Q-gram的长度
        double qGramSimilarity = calculateQGramSimilarity(s1, s2, q);
        System.out.println("Q-gram Similarity (Q=" + q + "): " + qGramSimilarity);
    }
}

        运行以上的程序,得到以下的执行结果:

Q-gram Similarity (Q=3): 0.5833333333333334

4、余弦相似性计算

        使用词嵌入(如word2vec或BERT)将单词转换为向量,并计算向量之间的余弦相似度。这里基于Apache 的common-text来进行余弦计算,看结果如何,首先在Pom.xml中引入以下资源。

<!-- 求解字符相似性 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-text</artifactId>
	<version>1.10.0</version>
</dependency>

        然后在Java中实现以下方法,请注意,这里是一种比较简单的方法,更精准的实现还要结合实际场景进行优化。

/**
*计算两个字符串的相似性
* @param args1
* @param args2
* @return
*/
private Double getSimilar(String args1,String args2) {
	Map<CharSequence, Integer> map = Arrays.stream(args1.split(""))
	     .collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));
	Map<CharSequence, Integer> map2 = Arrays.stream(args2.split(""))
	     .collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));

	CosineSimilarity cosineSimilarity = new CosineSimilarity();
	Double similar = cosineSimilarity.cosineSimilarity(map, map2);
	return similar;
}

        基于余弦的方法运行结果:

similar = 0.6726637889454885

        篇幅有限,这里不做很全面的覆盖测试,基于上面的代码,感兴趣的朋友和同学可以自己去做测试,根据不同的样例,得到的结果阈值比较令人想象不到,建议结合真实的数据进行测试,你会发现问题更大。如果要把这个应用于实战的话,建议不要采用上述模型,推荐采用TF-IDF(Term Frequency-Inverse Document Frequency)和余弦计算的方式。最后进行综合评分,将不同的相似度计算方法(如基于编辑的算法、基于令牌的方法、基于语义的方法)结合起来,并为每种方法分配一个权重,然后计算加权平均值。这样子计算出来的结果比较准确。更深入的内容,大家闲暇的时候可以自主实现。

二、基于余弦相似性的基地名称对比

        这里我们讲解如何把数据库中的基地列表信息和通过Excel表格整理的基地信息进行综合对比,通过余弦相似性和设置忽略词来提高准确度。作为一种参考的实现方案供大家参考。

1、加载百科中的基地信息列表

        要想将数据库中的基地信息和百科中的数据进行对比,首先要做的就是数据采集。通过把从百科采集的数据转换成excel,然后应用程序解析Excel数据,通过计算计算英文名称的相似性来进行对比。基础数据采集的方式,可以根据大家的熟悉程度,可以通过爬虫的形式进行介绍,也可以把表格直接复制到Exclel,直接进行Excle的读取成List列表后进行对比即可。这里我们以第二种方案来进行讲解。以下是从百科中节选的Excel中的数据列表。

管理设施代码基地英文名称基地中文名称用途驻地国家中文名驻地国家英文名驻地城市中文名
FAC 1054Camp Chitose千岁营通信日本Japan北海道千岁市
FAC 2001Misawa Air Base三泽空军基地航空基地日本Japan青森县三泽市
FAC 3013Yokota Air Base横田空军基地航空基地日本Japan东京都福生市
FAC 3016Fuchu Communications Station府中通讯站通信日本Japan东京都府中市
FAC 3019Tama Hills Recreation Center多摩之丘育乐中心娱乐日本Japan东京都稻城市
FAC 3048South Camp Drake AFN Transmitter Site南德雷克营美军电台转播站兵营日本Japan埼玉县和光市
FAC 3048Camp Asaka朝霞营兵营日本Japan埼玉县和光市
FAC 3049Tokorozawa Communications Station所泽通讯站通信日本Japan埼玉县所泽市
FAC 3056Owada Communication Site大和田通讯站通信日本Japan埼玉新座市
FAC 3162Yugi Communication Site由木通讯站通信日本Japan东京都八王子市
FAC 4100Sofu Communication Site祖生通讯站通信日本Japan山口县岩国市
FAC 5001Itazuke Auxiliary Airfield板付辅助飞行场空运货站日本Japan福冈市博多区
FAC 5073Sefurisan Liaison Annex脊振山辅助联络站通信日本Japan佐贺县神埼市
FAC 5091Tsushima Communication Site对马通讯站通信日本Japan长崎对马市
FAC 6004Okuma Rest Center奥间休息中心娱乐日本Japan冲绳国头村
FAC 6006Yaedake Communication Site八重岳通讯站通信日本Japan冲绳本部町
FAC 6022Kadena Ammunition Storage Area嘉手纳弹药储存区存储日本Japan冲绳恩纳村
FAC 6037Kadena Air Base嘉手纳空军基地航空基地日本Japan冲绳嘉手纳
FAC 6077Tori Shima Range鸟岛炸射练习场训练日本Japan冲绳久米岛
FAC 6078Idesuna Jima Range出砂岛炸射练习场训练日本Japan冲绳渡名喜村
FAC 6080Kume Jima Range久米岛炸射练习场训练日本Japan冲绳久米岛町
FAC 2070Shariki Communication Site车力通讯站通信日本Japan青森县津轻市
FAC 3004Akasaka Press Center (Hardy Barracks)赤坂新闻中心(哈迪军营)办公室日本Japan东京都港区
FAC 3067Yokohama North Dock横滨北坞港口设施日本Japan神奈川县横滨市

        上面只是一个示例,实际的表格有85条数据。

         我们需要将Excel中的数据进行导入到应用程序中,首先需要定义一个实体类:

package com.yelang.project.extend.militarytopics.domain;
import java.io.Serializable;
import com.yelang.framework.aspectj.lang.annotation.Excel;
import com.yelang.framework.aspectj.lang.annotation.Excel.Type;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class WebSiteMilitaryBase implements Serializable{
	private static final long serialVersionUID = -4620277223946004351L;
	@Excel(name = "设施管理代码", type = Type.IMPORT)
	private String manageCode;
	@Excel(name = "基地英文名称")
	private String enName;
	@Excel(name = "基地中文名称")
	private String cnName;
	@Excel(name = "用途")
	private String useTo;
	@Excel(name = "驻地国家中文名")
	private String cnCountry;
	@Excel(name = "驻地国家英文名")
	private String enCountry;
	@Excel(name = "驻地城市中文名")
	private String cnCity;
}

        然后定义Excel的读取方法,关键代码如下所示:

public void readJapanData() {
	try {
		File file = new File("C:/Users/Administrator/Desktop/基地/驻日美军基地.xlsx");
		FileInputStream fis = new FileInputStream(file);
		ExcelUtil<WebSiteMilitaryBase> util = new ExcelUtil<WebSiteMilitaryBase>(WebSiteMilitaryBase.class);
		List<WebSiteMilitaryBase> dataList = util.importExcel(fis);
		System.out.println(dataList.size());
		for(WebSiteMilitaryBase base : dataList) {
				System.out.println(base);
		}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

        运行一下代码,测试一下是否读取成功,如果在控制台中看到以下信息说明解析成功。

2、设置忽略词列表 

        其实忽略词和权重打分的作用是差不多的,忽略词就是在字符串中没有什么影响的词,这里需要注意的是要结合场景来说明。比如当前是均事领域,类似与Air base等这些在相关基地中的字符串中就可以忽略掉。忽略词设置好之后,在进行字符串的相似性计算时,需要把两个字符串进行忽略词替换。关键代码如下:

/**
* 去掉需要忽略的关键词
* @param source
* @return
*/
private String ignoreKeyWords(String source) {
	// Barracks 军营 Service Area 服务中心  Air Station 航空站 Air Base 空军基地 Camp 营地 Recreation Center 娱乐中心 Communications Station 通信站
	// Transmitter Site 发射站 Communication Site 通信站点 Training 训练 Airfield机场 Ammunition Depot 弹药库 Port 港口 Pier 码头 Dependent Housing 家属区
	// Depot 仓库 Landing Field 着陆场 Corps 兵团 Naval 海军
	String [] keyWords = {"Barracks","Service Area","Station","Air","Base","Camp","Area","Recreation Center","Communications","Station",
				"Transmitter","Site","Communication","Training","Airfield","Annex","Ammunition","Port","Pier","Dependent","Housing","Depot"
				,"Storage","Range","Center","Landing Field","Corps","Naval","Marine"};
	for(String keyword : keyWords) {
		source = source.replace(keyword, "").trim();
	}
	return source;
}

3、将数据库地名和Excel进行对比

        在这里 ,我们需要将需要对比的数据从数据库中查询出来,然后跟Excel表格中的进行对比。经过忽略词的设置后,我们对比最后的计算结果,最后得到两个字符串的相似性。当两个字符串的相似度大于90%,我们即可认为是统一地点,当然这里最好需要人工审核。

@Test
public void evalJapanCosineSimilarity() {
	QueryWrapper<UsaMilitaryBase> queryWrapper = new QueryWrapper<UsaMilitaryBase>();
	queryWrapper.isNull("cn_name");//查询基地中文名为空的数据
	List<UsaMilitaryBase> dbList = this.militaryBaseService.list(queryWrapper);
	System.out.println(dbList.size());
	try {
		File file = new File("C:/Users/Administrator/Desktop/基地/驻日美军基地.xlsx");
		FileInputStream fis = new FileInputStream(file);
		ExcelUtil<WebSiteMilitaryBase> util = new ExcelUtil<WebSiteMilitaryBase>(WebSiteMilitaryBase.class);
		List<WebSiteMilitaryBase> excelDataList = util.importExcel(fis);
		System.out.println(excelDataList.size());
		int index = 0;
		for(WebSiteMilitaryBase base : excelDataList) {
			for(UsaMilitaryBase dbBase : dbList) {
				String dbEnName = dbBase.getEnName();
				dbEnName = ignoreKeyWords(dbEnName);
				String excelEnName = base.getEnName();
				excelEnName = ignoreKeyWords(excelEnName);
				Double similar = this.getSimilar(dbEnName, excelEnName);
				if(similar >= 0.85) {
		System.out.println(dbEnName + "<==>" + excelEnName + "\t similar = " + similar);
					System.out.println(base);
					index ++;
				}else {
					continue;
				}
			}
		}
		System.out.println(index);
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

        下面我们来执行上述的代码,看看最终符合我们条件的有多少?

 

Misawa<==>Misawa	 similar = 0.9999999999999998
WebSiteMilitaryBase(manageCode=FAC 2001, enName=Misawa Air Base, cnName=三泽空军基地, useTo=航空基地, cnCountry=日本, enCountry=Japan, cnCity=青森县三泽市)
Idesuna Jima<==>Idesuna Jima	 similar = 1.0
WebSiteMilitaryBase(manageCode=FAC 6078, enName=Idesuna Jima Range, cnName=出砂岛炸射练习场, useTo=训练, cnCountry=日本, enCountry=Japan, cnCity=冲绳渡名喜村)
Kawakami<==>Kawakami	 similar = 1.0
WebSiteMilitaryBase(manageCode=FAC 4083, enName=Kawakami Ammunition Depot, cnName=川上弹药库, useTo=存储, cnCountry=日本, enCountry=Japan, cnCity=广岛县东广岛市)
Hiro<==>Hiro	 similar = 1.0
WebSiteMilitaryBase(manageCode=FAC 4084, enName=Hiro Ammunition Depot, cnName=广弹药库, useTo=存储, cnCountry=日本, enCountry=Japan, cnCity=广岛县吴市)
Kure  6<==>Kure  No.6	 similar = 0.8660254037844386
WebSiteMilitaryBase(manageCode=FAC 4152, enName=Kure Pier No.6, cnName=吴市6号码头, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=广岛县吴市)
Torii<==>Torii	 similar = 0.9999999999999999
WebSiteMilitaryBase(manageCode=FAC 6036, enName=Torii Communications Station, cnName=鸟居通讯站, useTo=通信, cnCountry=日本, enCountry=Japan, cnCity=冲绳县读谷村)
Naha<==>Naha	 similar = 1.0000000000000002
WebSiteMilitaryBase(manageCode=FAC 6064, enName=Naha Port, cnName=那霸港湾设施, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=冲绳县那霸市)
Fleet Activities Chinhae KS<==>United States Fleet Activities Yokosuka	 similar = 0.8653323061113575
WebSiteMilitaryBase(manageCode=FAC 3099, enName=United States Fleet Activities Yokosuka, cnName=横须贺美国舰队基地, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=神奈川县横须贺市)
Fleet Activities Chinhae KS (Yechon)<==>United States Fleet Activities Sasebo	 similar = 0.8560516500077061
WebSiteMilitaryBase(manageCode=FAC 5029, enName=United States Fleet Activities Sasebo, cnName=佐世保美国舰队基地, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=长崎县佐世保市)
Fleet Activities Chinhae KS<==>United States Fleet Activities Sasebo	 similar = 0.8994681014529727
WebSiteMilitaryBase(manageCode=FAC 5029, enName=United States Fleet Activities Sasebo, cnName=佐世保美国舰队基地, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=长崎县佐世保市)
Hiro<==>Hario	 similar = 0.8944271909999159
WebSiteMilitaryBase(manageCode=FAC 5119, enName=Hario Dependent Housing Area, cnName=针尾军眷住宅区, useTo=住宅, cnCountry=日本, enCountry=Japan, cnCity=长崎县佐世保市)
Fleet Activities Chinhae KS (Yongsan Garrison)<==>Makiminato  ( Kinser)	 similar = 0.8663164754169591
WebSiteMilitaryBase(manageCode=FAC 6056, enName=Makiminato Service Area (Camp Kinser), cnName=牧港补给地区(金瑟营), useTo=后勤, cnCountry=日本, enCountry=Japan, cnCity=冲绳县浦添市)
San Vito Dei Normanni<==>Makiminato  ( Kinser)	 similar = 0.8524007579586305
WebSiteMilitaryBase(manageCode=FAC 6056, enName=Makiminato Service Area (Camp Kinser), cnName=牧港补给地区(金瑟营), useTo=后勤, cnCountry=日本, enCountry=Japan, cnCity=冲绳县浦添市)
13

      可以很直观的看到,经过计算,有的地名已经完全匹配,比如Hiro<==>Hiro     similar = 1.0和Idesuna Jima<==>Idesuna Jima     similar = 1.0。这些数据可以认为是一个地点了。

三、总结

        以上就是本文的主要内容,博客以Java编程为例,讲解了在Java中求解两个字符串的几种方法。通过求解编辑距离、Q-gram Matching、还有余弦相似性计算,通过对比不同的方法,调用Apache 的Common-text中基于余弦的字符相似性得到了比较比错的结果。最后讲解了一个实际的案例,将之前我们采集的漂亮数据库数据和百科的数据进行对齐。为下一步做数据关联和挖掘打下坚实的基础。行文仓促,定有许多的不足之处,如有任何不当或者表达不准确的地方,还恳请各位专家和朋友在评论区留言平指正,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2047452.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言音频.wav读写示例

1 .wav格式说明 一. RIFF 概念 在 Windows 环境下&#xff0c;大部分的多媒体文件都依循着一种结构来存放信息&#xff0c;这种结构称为"资源互换文件格式"(Resources lnterchange File Format)&#xff0c;简称 RIFF。例如声音的 WAV 文件、视频的 AV1 文件等等均…

EmguCV学习笔记 VB.Net 2.4 Image类

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV学习笔记目录 Vb.net EmguCV学习笔记目录 C# 笔者的博客网址&#xff1a;VB.Net-CSDN博客 教程相关说明以及如何获得pdf教…

【图解秒杀系列】秒杀技术点——秒杀按钮点亮、削峰

【图解秒杀系列】秒杀技术点——秒杀按钮点亮、削峰 秒杀按钮点亮涉及的问题以及解决办法处理流程 削峰答题 & 验证码具体流程 排队 秒杀按钮点亮 在秒杀场景中&#xff0c;秒杀商品页面是需要处理按钮点亮的逻辑的。在秒杀未开始前&#xff0c;按钮置灰&#xff0c;不可点…

POSIX信号量semaphore实现线程同步

POSIX标准定义了信号量接口如下&#xff0c;常常用于线程间同步。 #include <semaphore.h>int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_destroy(sem_t *sem); int sem_post(sem_t *sem); int sem_wait(sem_t *sem); sem_init()在sem指向的地址…

微信小程序反编译工具

目录 介绍 工程结构还原 微信开发者工具运行 如何查看当前运行版本? 开启小程序F12 重新打包运行 效果示例 安装 用法 参数说明 获取微信小程序AppID 文件夹名即为AppID 下载地址 介绍 纯Golang实现,一个用于自动化反编译微信小程序的工具,小程序安全利器, 自…

【杂谈】-8个常用的Python图像操作库

8个常用的Python图像操作库 文章目录 8个常用的Python图像操作库1、OpenCV2、Pillow&#xff08;PIL&#xff09;3、Scikit Image4、Numpy5、SciPy6、Mahotas7、SimpleITK8、Matplotlib 在当今世界&#xff0c;数据在每个行业垂直领域中都发挥着至关重要的作用。图像可以是提取…

Redis 操作的原子性及其保证机制

Redis 操作的原子性及其保证机制 1、单命令的原子性2、事务的原子性3、并发操作的考虑4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Redis 的操作之所以是原子性的&#xff0c;主要得益于其单线程的执行模型。这种模型确保了每个命…

5.9.8 最优化控制初探——PID参数优化

总目录&#xff1a;http://t.csdnimg.cn/YDe8m 5.9.8 最优化控制初探——PID参数优化 之前在“A_2_PID控制转速例程”例程中&#xff0c;PID参数是手动调节的。然而在已经获得系统完整数学模型的情况下&#xff0c;我们可以使用效率更高的方法&#xff0c;即最优化控制。先来看…

Nios II新建项目

1.Nios II Application and BSP form Template BSP:board support package&#xff08;板级支持包&#xff09; 2.Nios II Sotware Examples SOPC Information File name:选择项目文件夹下的 .sopcinfo 文件 Project name:自定义名称 Project location:Use default locatio…

删除镜像报容器依赖错误

1、删除镜像报容器依赖错误 出现这个错误的原因是因为5303b5323a4c容器使用了此镜像。解决&#xff1a;先停止容器、删除容器、之后再镜像即可。 2、查看镜像对应的容器 # docker ps -a | grep 611a37aa5ffc 3、先停止容器 # docker stop 5303b5323a4c 4、删除容器 # do…

Spring Boot: 2.7.x 至 2.7.18 及更旧的版本,漏洞说明

本文提供的修复指南将帮助开发者有效规避 CVE-2024-38808 和 CVE-2024-38809 的风险。如果你正在使用老版本的 Spring Boot&#xff0c;请尽快参考本文进行修复与升级。 此漏洞来源于spring官网&#xff1a;https://spring.io/blog/2024/08/14/spring-framework-releases-fixe…

flink车联网项目前篇:业务实现1(第67天)

系列文章目录 业务实现 3.1 创建catalog 3.1.1 vvp 3.1.2 mysqlcdc 3.1.2.1 使用限制 3.1.2.2 配置MySQL Catalog 3.1.3 xxxxpm 3.1.3.1 下载Paimon插件 3.1.3.2 在MaxCompute项目中上传Paimon插件 3.1.3.3 创建自定义Catalog类型 3.1.3.5 配置catalog 3.1.4 xxxxx 3.1.4.1 背…

Linux设置yum源为阿里云镜像源

一、验证网络是否可以连接阿里云镜像 #验证网络是否可以连接阿里云镜像 ping mirrors.aliyun.com如果ping不通&#xff0c;则找一台可以连接外网的电脑&#xff0c;ping一下mirrors.aliyun.com&#xff0c;找到mirrors.aliyun.com对应的ip。 二、 手动配置 #删除原yum源 rm -…

微信小程序免费《短视频去水印》

分享一个uniapp开发的微信小程序免费《短视频去水印》小程序 <template><view class"content"><view class"area-wrap"><textarea name"" v-model"state.content" maxlength"800" id"" cols…

接口自动化测试怎么做?该怎么学习

一. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…

《黑神话:悟空》媒体评分解禁 M站均分82

《黑神话&#xff1a;悟空》媒体评分现已解禁&#xff0c;截止发稿时&#xff0c;M站共有43家媒体评测&#xff0c;均分为82分。 部分媒体评测&#xff1a; God is a Geek 100&#xff1a; 毫无疑问&#xff0c;《黑神话&#xff1a;悟空》是今年最好的动作游戏之一&#xff…

linux系统安装mysql服务

linux系统安装mysql服务 1.下载安装包2.下载压缩文件解压安装3. 安装完启动服务4.查看安装密码5.使用上述密码登录6.修改密码7.创建一个root可以在任意主机远程连接数据库8.远程登录成功 1.下载安装包 https://downloads.mysql.com/archives/community/ mysql下载地址 2.下载…

【AI安防】YOLOv8 + OpenVINO2023 + QT5 电子围栏预警系统

引言 电子围栏是一种利用无线通信技术和地理信息系统实现的虚拟边界&#xff0c;用于监控和控制被监控对象的位置。它可以帮助我们实现对特定区域内的自定义对象进行实时检测、定位与跟踪。本文介绍了一种基于YOLOv8 OpenVINO2023 QT5 联合打造的实时高效、多线程、自定义对…

Keepalived简介以及常见用途

一、Keepalived 简介 Keepalived 是一个高可用性&#xff08;HA&#xff09;解决方案&#xff0c;主要用于实现 Linux 系统的负载均衡和故障转移。它最初设计用于与 LVS&#xff08;Linux Virtual Server&#xff09;一起使用&#xff0c;但也可以独立使用&#xff0c;主要功能…

0815,析构函数,拷贝构造函数,赋值运算符函数

来自同济医院的问候 目录 01&#xff1a;对象创建 001.cc 003size.cc 02&#xff1a;对象销毁 004pointer.cc 005destroytime.cc 03&#xff1a;本类型对象的复制 3.1 拷贝构造函数 006cp.cc 007cptime.cc 008recursion.cc 009rightleft.cc 3.2 赋值运算符函数 …