TF-IDF笔记

信息检索的历史发展过程中,出现了很多的模型,模型就是实际问题的抽象。如布尔模型、向量模型。
布尔模型以集合的布尔运算为基础,查询效率高,但只能适用简单搜索问题,同时还要求用户要按照要求拼凑查询串,只能用于特定领域。
向量模型把查询串和文档都是为词所构成的多维向量,查询与文档的相关性用向量间的夹角来表示。向量计算不适用于大规模数据。
TF-IDF(Term Frequency Inverse Doucument Frequency)模型,中文意思是:词频-逆文档频率。
TF-IDF核心思想是“给定的查询串q和文档d的匹配度问题”,这个在搜索引擎中使用广泛。 
TF(Term Frequency),即词频,一个词q在文中出现的次数(tf = len(q)/len(all)),一般来说,一个词在一篇文章中出现的次数越多,则这篇文章的意思就越有可能与这个词相关,但是有些词,如“的”、“是”,在文中出现的次数一般都很高,但都没有实际的意义。所以,词频可以衡量一个词与文的相关性,但不能只用它。
IDF(Inverse Doucument Frequency),逆文档频率,即文档总数n与词q所出现文件数n1的比值的对数log(n/n1)。其思想是:词q如果在某篇文章中出现,而在其他文章中很少出现,则q具有很好的区分性,能大致代表出现较多的那篇文章。
最后TF-IDF的值就是:tf*idf,用来表示查询串与文档d的匹配度。这个匹配度,可以从概率的角度来理解,即用户通过查询串q,期望获得文档d的概率。在结果展示中,按从大到小的顺序排列即可,当然,实际中可能还有更多的问题要考虑。

下面是我用Java的实现:
package cn.zhf.cluster;

import java.io.*;
import java.util.*;

import org.junit.Test;
/**
 * tf-idf实现类
 * 如果是中文,其中input中的txt文件需要先用空格分好词
 * 此类只是简单实现,还有很多问题
 * @author zhaohuafei
 *
 */
public class TFIDF {
    public static final String FILE = "E:/input2/input2.txt";// 单个文件地址
    public static final String FILES = "E:/input2/";// 文档所在目录

    /**
     * Term Frequency - Inverse Document Frequency 给定串在给定文件列表中某一文件的 逆文档频率
     * 
     * @param term
     * @param file
     * @param files
     * @return
     */
    public double tfidf(String term, File file, File[] files) {
        int tf = tf(term, file);
        double idf = idf(term, files);
        return tf * idf;
    }

    /**
     * Term Frequency of a term(word) in a file
     * 
     * @param term
     * @param file
     * @return
     */
    public int tf(String term, File file) {
        if (tfmap(file).get(term) == null)
            return 0;
        return tfmap(file).get(term);
    }

    /**
     * Inverse Document Frequency the number of documents that a term appears
     * 
     * @param term
     * @list the documents that this term appears
     * @return
     */
    public double idf(String term, File[] files) {
        List<Map<String, String>> list = idfmap(files);
        int count = 0;// term出现的文件数
        for (int i = 0; i < list.size(); i++) {
            Map<String, String> map = list.get(i);
            for (Map.Entry<String, String> m : map.entrySet()) {
                if (m.getValue().equals(term))
                    count++;
            }
        }
        return Math.log(files.length / count);
    }

    /**
     * All Term Frequency Map in a file
     * 
     * @param file
     * @return
     */
    public Map<String, Integer> tfmap(File file) {
        Map<String, Integer> map = new HashMap<String, Integer>();
        List<String> list = segment(file);
        for (String term : list)
            map.put(term, !map.containsKey(term) ? 1 : map.get(term) + 1);
        return map;
    }

    /**
     * All Inverse Document Frequency as a map
     * 
     * @param files
     * @return map<filename,term>
     */
    public List<Map<String, String>> idfmap(File[] files) {
        Map<String, Integer> maptf = new HashMap<String, Integer>();
        List<Map<String, String>> list = new LinkedList<Map<String, String>>();
        for (int i = 0; i < files.length; i++) {
            maptf = tfmap(files[i]);
            for (Map.Entry<String, Integer> m : maptf.entrySet()) {
                String key = m.getKey();
                Map<String, String> map = new HashMap<String, String>();
                map.put(files[i].getName(), key);
                list.add(map);
            }
        }
        return list;
    }

    /**检索方法
     * 返回(文档名,tfidf值)
     * 
     * @param query
     * 查询串
     * @return <文档名,tfidf值>,按tfidf值排序
     */
    public Map<String, Double> search(String query, File[] files) {
        Map<String, Double> map = new HashMap<String, Double>();
        for (int i = 0; i < files.length; i++) {
            int tf = tf(query, files[i]);
            if (tf == 0)
                continue;
            double idf = idf(query, files);
            double tfidf = tf * idf;
            map.put(files[i].getName(), tfidf);
        }
        map = sortMapByValueAsc(map);
        return map;
    }

    /**
     * map按值排序 asc
     * 
     * @param map
     * @return
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortMapByValueAsc(
            Map<K, V> map) {
        List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(
                map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
            @Override
            public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
                return (o2.getValue()).compareTo(o1.getValue());
            }
        });
        Map<K, V> ret = new LinkedHashMap<K, V>();
        for (Map.Entry<K, V> m : list) {
            ret.put(m.getKey(), m.getValue());
        }
        return ret;
    }

    /**
     * 简单的分词,假设句子都是以空格隔开的 TODO
     * 
     * @param file
     * @return
     */
    public List<String> segment(File file) {
        List<String> list = new ArrayList<String>();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    new FileInputStream(file), "gbk"));
            String tmp = null, str = null;
            while ((str = br.readLine()) != null) {
                tmp += str;
            }
            String[] s = tmp.split("\\s");
            for (int i = 0; i < s.length; i++)
                list.add(s[i].trim());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    // 以下均为测试
    @Test
    public void test3() {
        int tf = tf("的", new File(FILE));
        System.out.println("TF = " + tf);
        Map<String, Double> map = search("的", new File(FILES).listFiles());
        for (Map.Entry<String, Double> m : map.entrySet()) {
            System.out.println(m.getKey() + "-->" + m.getValue());
        }
    }

    public void test2() {
        File file = new File(FILES);
        File[] files = file.listFiles();
        List<Map<String, String>> list = idfmap(files);
        for (int i = 0; i < list.size(); i++) {
            Map<String, String> map = list.get(i);
            for (Map.Entry<String, String> m : map.entrySet()) {
                System.out.println(m.getKey() + "-->" + m.getValue());
            }
        }
        double tfidf = tfidf("的", new File(FILE), new File(FILES).listFiles());
        System.out.println("count = " + tfidf);
    }

    public void test1() {
        File file = new File(FILE);
        List<String> list = segment(file);
        for (String str : list)
            System.out.println(str);
    }

    public void test() {
        File file = new File(FILES);
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            Map<String, Integer> map = tfmap(files[i]);
            for (Map.Entry<String, Integer> m : map.entrySet()) {
                System.out.println(m.getKey() + "-->" + m.getValue());
            }
        }
    }

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值