?? barrel.c
字號:
/* Managing the connection between document-vectors (wi2dvf's) and cdocs Copyright (C) 1997 Andrew McCallum Written by: Andrew Kachites McCallum <mccallum@cs.cmu.edu> This file is part of the Bag-Of-Words Library, `libbow'. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation, version 2. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA */#include <bow/libbow.h>static int _bow_barrel_version = -1;#define BOW_DEFAULT_BARREL_VERSION 3/* Old, deprecated identifiers for methods. *//* Identifiers for methods */typedef enum _bow_method_id { bow_method_id_tfidf_words, /* TFIDF/Rocchio */ bow_method_id_tfidf_log_words, bow_method_id_tfidf_log_occur, bow_method_id_tfidf_prtfidf, bow_method_id_naivebayes, /* Naive Bayes */ bow_method_id_prind, /* Fuhr's Probabilistic Indexing */ bow_method_id_max} bow_method_id;bow_method* _old_bow_methods[bow_method_id_max] = { [bow_method_id_tfidf_words] = &bow_method_tfidf_words, [bow_method_id_tfidf_log_words] = &bow_method_tfidf_log_words, [bow_method_id_tfidf_log_occur] = &bow_method_tfidf_log_occur, [bow_method_id_naivebayes] = &bow_method_naivebayes, [bow_method_id_prind] = &bow_method_prind};/* Create a new, empty `bow_barrel', with cdoc's of size ENTRY_SIZE and cdoc free function FREE_FUNC.*/bow_barrel *bow_barrel_new (int word_capacity, int class_capacity, int entry_size, void (*free_func)()){ bow_barrel *ret; ret = bow_malloc (sizeof (bow_barrel)); ret->cdocs = bow_array_new (class_capacity, entry_size, free_func); ret->wi2dvf = bow_wi2dvf_new (word_capacity); ret->method = (bow_argp_method ? : bow_method_at_name (bow_default_method_name)); return ret;}static void_bow_barrel_cdoc_free (bow_cdoc *cdoc){ if (cdoc->filename) free ((void*)(cdoc->filename));}/* Add statistics about the document described by CDOC and WV to the BARREL. */intbow_barrel_add_document (bow_barrel *barrel, bow_cdoc *cdoc, bow_wv *wv){ int di; /* Add the CDOC. (This makes a new copy of CDOC in the array.) */ di = bow_array_append (barrel->cdocs, cdoc); /* Add the words in WV. */ bow_wi2dvf_add_di_wv (&(barrel->wi2dvf), di, wv); return di;}/* Add statistics to the barrel BARREL by indexing all the documents found when recursively decending directory DIRNAME. Return the number of additional documents indexed. */intbow_barrel_add_from_text_dir (bow_barrel *barrel, const char *dirname, const char *except_name, int class){ int text_file_count, binary_file_count; int barrel_index_file (const char *filename, void *context) { FILE *fp; bow_cdoc cdoc; int di; /* a document index */ /* If the filename matches the exception name, return immediately. */ if (except_name && !strcmp (filename, except_name)) return 0; if (!(fp = fopen (filename, "r"))) bow_error ("Couldn't open file `%s' for reading.", filename); if (bow_fp_is_text (fp)) { /* The file contains text; snarf the words and put them in the WI2DVF map. */ cdoc.type = model; cdoc.class = class; cdoc.prior = 1.0f; assert (cdoc.class >= 0); cdoc.filename = strdup (filename); assert (cdoc.filename); /* Add the CDOC to CDOCS, and determine the "index" of this document. */ di = bow_array_append (barrel->cdocs, &cdoc); /* Add all the words in this document. */ bow_wi2dvf_add_di_text_fp (&(barrel->wi2dvf), di, fp); text_file_count++; } else { bow_verbosify (bow_progress, "\nFile `%s' skipped because not text\n", filename); binary_file_count++; } fclose (fp); bow_verbosify (bow_progress, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" "%6d : %6d", text_file_count, bow_num_words ()); return 1; } bow_verbosify (bow_progress, "Gathering stats... files : unique-words :: " " "); text_file_count = binary_file_count = 0; bow_map_filenames_from_dir (barrel_index_file, 0, dirname, ""); bow_verbosify (bow_progress, "\n"); if (binary_file_count > text_file_count) bow_verbosify (bow_quiet, "Found mostly binary files, which were ignored.\n"); return text_file_count;}/* Call this on a vector-per-document barrel to set the CDOC->PRIOR's so that the CDOC->PRIOR's for all documents of the same class sum to 1. */voidbow_barrel_set_cdoc_priors_to_class_uniform (bow_barrel *barrel){ int *ci2dc; /* class index 2 document count */ int ci2dc_size = 100; int ci; int di; bow_cdoc *cdoc; int total_model_docs = 0; int num_non_zero_ci2dc_entries = 0; ci2dc = bow_malloc (sizeof (int) * ci2dc_size); for (ci = 0; ci < ci2dc_size; ci++) ci2dc[ci] = 0; for (di = 0; di < barrel->cdocs->length; di++) { cdoc = bow_array_entry_at_index (barrel->cdocs, di); if (cdoc->class >= ci2dc_size) { /* CI2DC must grow to accommodate larger "class index" */ int old_size = ci2dc_size; ci2dc_size *= 2; ci2dc = bow_realloc (ci2dc, sizeof (int) * ci2dc_size); for ( ; old_size < ci2dc_size; old_size++) ci2dc[old_size] = 0; } if (cdoc->type == model) { if (ci2dc[cdoc->class] == 0) num_non_zero_ci2dc_entries++; ci2dc[cdoc->class]++; total_model_docs++; } } for (di = 0; di < barrel->cdocs->length; di++) { cdoc = bow_array_entry_at_index (barrel->cdocs, di); if (cdoc->type == model) { cdoc->prior = (1.0 / (num_non_zero_ci2dc_entries * ci2dc[cdoc->class])); assert (cdoc->prior >= 0); } }#if 0 fprintf (stderr, "Infogain post-prior-setting\n"); bow_infogain_per_wi_print (stderr, barrel, num_non_zero_ci2dc_entries, 5);#endif /* Do some sanity checks. */ { float prior_total = 0; for (di = 0; di < barrel->cdocs->length; di++) { cdoc = bow_array_entry_at_index (barrel->cdocs, di); if (cdoc->type == model) prior_total += cdoc->prior; } assert (prior_total < 1.1 && prior_total > 0.9); } free (ci2dc);}/* Modify the BARREL by removing those entries for words that are not in the int/str mapping MAP. */voidbow_barrel_prune_words_not_in_map (bow_barrel *barrel, bow_int4str *map){ int wi; int max_wi = MIN (barrel->wi2dvf->size, bow_num_words()); assert (max_wi); /* For each word in MAP. */ for (wi = 0; wi < max_wi; wi++) { if (bow_str2int_no_add (map, bow_int2word (wi)) == -1) { /* Word WI is not in MAP. Remove it from the BARREL. */ bow_wi2dvf_remove_wi (barrel->wi2dvf, wi); } }}/* Modify the BARREL by removing those entries for words that are not among the NUM_WORDS_TO_KEEP top words, by information gain. This function is similar to BOW_WORDS_KEEP_TOP_BY_INFOGAIN(), but this one doesn't change the word-int mapping. */voidbow_barrel_keep_top_words_by_infogain (int num_words_to_keep, bow_barrel *barrel, int num_classes){ float *wi2ig; int wi2ig_size; int wi, i; struct wiig_list_entry { float ig; int wi; } *wiig_list; /* For sorting the above entries. */ int compare_wiig_list_entry (const void *e1, const void *e2) { if (((struct wiig_list_entry*)e1)->ig > ((struct wiig_list_entry*)e2)->ig) return -1; else if (((struct wiig_list_entry*)e1)->ig == ((struct wiig_list_entry*)e2)->ig) return 0; else return 1; } if (num_words_to_keep == 0) return; /* Unhide "document vectors" for all WI's */ bow_wi2dvf_unhide_all_wi (barrel->wi2dvf); /* Get the information gain of all the words. */ wi2ig = bow_infogain_per_wi_new (barrel, num_classes, &wi2ig_size); /* Make a list of the info gain numbers paired with their WI's, in prepartion for sorting. */ wiig_list = alloca (sizeof (struct wiig_list_entry) * wi2ig_size); for (wi = 0; wi < wi2ig_size; wi++) { wiig_list[wi].wi = wi; wiig_list[wi].ig = wi2ig[wi]; } /* Sort the list */ qsort (wiig_list, wi2ig_size, sizeof (struct wiig_list_entry), compare_wiig_list_entry);#if 1 for (i = 0; i < 5; i++) fprintf (stderr, "%20.10f %s\n", wiig_list[i].ig, bow_int2word (wiig_list[i].wi));#endif bow_verbosify (bow_progress,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -