java实现Word2Vec计算语义相似度例子,详细注释,AI入门学习,附源码,预训练文件

宅男的福音 2024-09-20 16:31:03 阅读 67

1.准备工作,源码以及预训练文件

源码以及预训练文件比较大下载地址https://pan.quark.cn/s/aeb85eaf95e2

2.核心代码

<code>package org.example;

import com.huaban.analysis.jieba.JiebaSegmenter;

import org.deeplearning4j.models.embeddings.loader.WordVectorSerializer;

import org.deeplearning4j.models.word2vec.Word2Vec;

import org.nd4j.linalg.api.ndarray.INDArray;

import org.nd4j.linalg.factory.Nd4j;

import java.io.BufferedInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.*;

import java.util.stream.Collectors;

public class Main {

public static void main(String[] args) throws IOException {

// 输入的两个句子

String input1 = "一寸光阴一寸金,寸金难买寸光阴。";

String input2 = "光阴似箭";

// 词向量模型文件路径

String modelFile = "baike_26g_news_13g_novel_229g.bin";

// 读取词向量模型文件

InputStream is = ClassLoader.getSystemResourceAsStream(modelFile);

BufferedInputStream bufferedInputStream = new BufferedInputStream(Objects.requireNonNull(is), 1024 * 1024);

Word2Vec word2VecModel = WordVectorSerializer.readBinaryModel(bufferedInputStream, false, true);

// 计算并输出两个句子的相似度

System.out.println(sentenceSimilarity(input1, input2, word2VecModel));

}

/**

* 根据文本内容获取对应的词向量列表

* @param text 文本内容

* @param model 词向量模型

* @return 词向量列表

*/

private static List<INDArray> getWordVectors(String text, Word2Vec model) {

// 将文本分词

List<String> words = segmentWords(text.toLowerCase(Locale.getDefault()));

// 创建一个列表来存储词向量

List<INDArray> wordVectors = new ArrayList<>(words.size());

for (String word : words) {

if (model.hasWord(word)) {

wordVectors.add(model.getWordVectorMatrix(word));

} else {

// 如果单词不在词汇表中,使用默认向量(这里使用零向量)

int vectorSize = model.getLayerSize(); // 获取词向量的大小

INDArray defaultVector = Nd4j.zeros(1, vectorSize); // 创建零向量

wordVectors.add(defaultVector);

}

}

return wordVectors;

}

/**

* 对句子进行分词处理

* @param sentence 待分词的句子

* @return 分词后的词语列表

*/

private static List<String> segmentWords(String sentence) {

JiebaSegmenter segmenter = new JiebaSegmenter();

return segmenter.sentenceProcess(sentence).stream()

.filter(e -> !" ".equals(e) && !e.isEmpty())

.collect(Collectors.toList());

}

/**

* 计算两个向量的余弦相似度

* @param vec1 第一个向量

* @param vec2 第二个向量

* @return 余弦相似度值

*/

private static double cosineSimilarity(INDArray vec1, INDArray vec2) {

// 计算两个向量的点积

double dotProduct = vec1.mulRowVector(vec2).sumNumber().doubleValue();

// 计算两个向量的模长

double norm1 = vec1.norm2Number().doubleValue();

double norm2 = vec2.norm2Number().doubleValue();

// 计算余弦相似度

return dotProduct / (norm1 * norm2);

}

/**

* 计算两个句子的相似度

* @param sentence1 第一个句子

* @param sentence2 第二个句子

* @param model 词向量模型

* @return 句子相似度值

*/

private static double sentenceSimilarity(String sentence1, String sentence2, Word2Vec model) {

List<INDArray> vectors1 = getWordVectors(sentence1, model);

List<INDArray> vectors2 = getWordVectors(sentence2, model);

INDArray avgVector1 = getAverageVector(vectors1, model.getLayerSize());

INDArray avgVector2 = getAverageVector(vectors2, model.getLayerSize());

return cosineSimilarity(avgVector1, avgVector2);

}

/**

* 计算一组向量的平均值向量

* @param vectors 向量列表

* @param modelSize 向量维度大小

* @return 平均向量

*/

private static INDArray getAverageVector(List<INDArray> vectors, int modelSize) {

INDArray sumVector = Nd4j.zeros(1, modelSize); // 创建一个与第一个向量形状相同的零向量

for (INDArray vector : vectors) {

sumVector.addiRowVector(vector); // 使用addi进行原地操作

}

INDArray indArray = sumVector.div(vectors.size());

sumVector.close();

return indArray; // 将总和除以向量数量以获得平均值

}

}

4. 预训练文件

image.png

4.运行结果

image.png

可以下载源码跑一下看看,体验一下语义相似度的魅力源码下载

觉得有用请点赞,有问题请在评论区留言



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。