081020_文本分类(Text Classification)

About Feature Generator

关于特征生成

1.  Change all the letters to lowercase, with a stemmer manipulation, and remove all the punctuations

    转换所有的字母至小写,进行stemmer处理,去除标点符号

2.  Deal with each feature with TF.IDF, take the features above threshold

    对每个特征进行TF.IDF处理,选取阈值以上的特征

3.  One Algorithm for Stemmer

    一个Stemmer的实例算法

  1. package com.featheast.bow;
  2. /*
  3.  Porter stemmer in Java. The original paper is in
  4.  Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,
  5.  no. 3, pp 130-137,
  6.  See also http://www.tartarus.org/~martin/PorterStemmer
  7.  History:
  8.  Release 1
  9.  Bug 1 (reported by Gonzalo Parra 16/10/99) fixed as marked below.
  10.  The words 'aed', 'eed', 'oed' leave k at 'a' for step 3, and b[k-1]
  11.  is then out outside the bounds of b.
  12.  Release 2
  13.  Similarly,
  14.  Bug 2 (reported by Steve Dyrdahl 22/2/00) fixed as marked below.
  15.  'ion' by itself leaves j = -1 in the test for 'ion' in step 5, and
  16.  b[j] is then outside the bounds of b.
  17.  Release 3
  18.  Considerably revised 4/9/00 in the light of many helpful suggestions
  19.  from Brian Goetz of Quiotix Corporation (brian@quiotix.com).
  20.  Release 4
  21.  */
  22. import java.io.*;
  23. /**
  24.  * Stemmer, implementing the Porter Stemming Algorithm
  25.  * 
  26.  * The Stemmer class transforms a word into its root form. The input word can be
  27.  * provided a character at time (by calling add()), or at once by calling one of
  28.  * the various stem(something) methods.
  29.  */
  30. class Stemmer {
  31.     private char[] b;
  32.     private int i, /* offset into b */
  33.     i_end, /* offset to end of stemmed word */
  34.     j, k;
  35.     private static final int INC = 50;
  36.     /* unit of size whereby b is increased */
  37.     public Stemmer() {
  38.         b = new char[INC];
  39.         i = 0;
  40.         i_end = 0;
  41.     }
  42.     /**
  43.      * Add a character to the word being stemmed. When you are finished adding
  44.      * characters, you can call stem(void) to stem the word.
  45.      */
  46.     public void add(char ch) {
  47.         if (i == b.length) {
  48.             char[] new_b = new char[i + INC];
  49.             for (int c = 0; c < i; c++)
  50.                 new_b[c] = b[c];
  51.             b = new_b;
  52.         }
  53.         b[i++] = ch;
  54.     }
  55.     /**
  56.      * Adds wLen characters to the word being stemmed contained in a portion of
  57.      * a char[] array. This is like repeated calls of add(char ch), but faster.
  58.      */
  59.     public void add(char[] w, int wLen) {
  60.         if (i + wLen >= b.length) {
  61.             char[] new_b = new char[i + wLen + INC];
  62.             for (int c = 0; c < i; c++)
  63.                 new_b[c] = b[c];
  64.             b = new_b;
  65.         }
  66.         for (int c = 0; c < wLen; c++)
  67.             b[i++] = w[c];
  68.     }
  69.     /**
  70.      * After a word has been stemmed, it can be retrieved by toString(), or a
  71.      * reference to the internal buffer can be retrieved by getResultBuffer and
  72.      * getResultLength (which is generally more efficient.)
  73.      */
  74.     public String toString() {
  75.         return new String(b, 0, i_end);
  76.     }
  77.     /**
  78.      * Returns the length of the word resulting from the stemming process.
  79.      */
  80.     public int getResultLength() {
  81.         return i_end;
  82.     }
  83.     /**
  84.      * Returns a reference to a character buffer containing the results of the
  85.      * stemming process. You also need to consult getResultLength() to determine
  86.      * the length of the result.
  87.      */
  88.     public char[] getResultBuffer() {
  89.         return b;
  90.     }
  91.     /* cons(i) is true <=> b[i] is a consonant. */
  92.     private final boolean cons(int i) {
  93.         switch (b[i]) {
  94.         case 'a':
  95.         case 'e':
  96.         case 'i':
  97.         case 'o':
  98.         case 'u':
  99.             return false;
  100.         case 'y':
  101.             return (i == 0) ? true : !cons(i - 1);
  102.         default:
  103.             return true;
  104.         }
  105.     }
  106.     /*
  107.      * m() measures the number of consonant sequences between 0 and j. if c is a
  108.      * consonant sequence and v a vowel sequence, and <..> indicates arbitrary
  109.      * presence,
  110.      * 
  111.      * <c><v> gives 0 <c>vc<v> gives 1 <c>vcvc<v> gives 2 <c>vcvcvc<v> gives
  112.      * 3 ....
  113.      */
  114.     private final int m() {
  115.         int n = 0;
  116.         int i = 0;
  117.         while (true) {
  118.             if (i > j)
  119.                 return n;
  120.             if (!cons(i))
  121.                 break;
  122.             i++;
  123.         }
  124.         i++;
  125.         while (true) {
  126.             while (true) {
  127.                 if (i > j)
  128.                     return n;
  129.                 if (cons(i))
  130.                     break;
  131.                 i++;
  132.             }
  133.             i++;
  134.             n++;
  135.             while (true) {
  136.                 if (i > j)
  137.                     return n;
  138.                 if (!cons(i))
  139.                     break;
  140.                 i++;
  141.             }
  142.             i++;
  143.         }
  144.     }
  145.     /* vowelinstem() is true <=> 0,...j contains a vowel */
  146.     private final boolean vowelinstem() {
  147.         int i;
  148.         for (i = 0; i <= j; i++)
  149.             if (!cons(i))
  150.                 return true;
  151.         return false;
  152.     }
  153.     /* doublec(j) is true <=> j,(j-1) contain a double consonant. */
  154.     private final boolean doublec(int j) {
  155.         if (j < 1)
  156.             return false;
  157.         if (b[j] != b[j - 1])
  158.             return false;
  159.         return cons(j);
  160.     }
  161.     /*
  162.      * cvc(i) is true <=> i-2,i-1,i has the form consonant - vowel - consonant
  163.      * and also if the second c is not w,x or y. this is used when trying to
  164.      * restore an e at the end of a short word. e.g.
  165.      * 
  166.      * cav(e), lov(e), hop(e), crim(e), but snow, box, tray.
  167.      * 
  168.      */
  169.     private final boolean cvc(int i) {
  170.         if (i < 2 || !cons(i) || cons(i - 1) || !cons(i - 2))
  171.             return false;
  172.         {
  173.             int ch = b[i];
  174.             if (ch == 'w' || ch == 'x' || ch == 'y')
  175.                 return false;
  176.         }
  177.         return true;
  178.     }
  179.     private final boolean ends(String s) {
  180.         int l = s.length();
  181.         int o = k - l + 1;
  182.         if (o < 0)
  183.             return false;
  184.         for (int i = 0; i < l; i++)
  185.             if (b[o + i] != s.charAt(i))
  186.                 return false;
  187.         j = k - l;
  188.         return true;
  189.     }
  190.     /*
  191.      * setto(s) sets (j+1),...k to the characters in the string s, readjusting
  192.      * k.
  193.      */
  194.     private final void setto(String s) {
  195.         int l = s.length();
  196.         int o = j + 1;
  197.         for (int i = 0; i < l; i++)
  198.             b[o + i] = s.charAt(i);
  199.         k = j + l;
  200.     }
  201.     /* r(s) is used further down. */
  202.     private final void r(String s) {
  203.         if (m() > 0)
  204.             setto(s);
  205.     }
  206.     /*
  207.      * step1() gets rid of plurals and -ed or -ing. e.g.
  208.      * 
  209.      * caresses -> caress ponies -> poni ties -> ti caress -> caress cats -> cat
  210.      * 
  211.      * feed -> feed agreed -> agree disabled -> disable
  212.      * 
  213.      * matting -> mat mating -> mate meeting -> meet milling -> mill messing ->
  214.      * mess
  215.      * 
  216.      * meetings -> meet
  217.      * 
  218.      */
  219.     private final void step1() {
  220.         if (b[k] == 's') {
  221.             if (ends("sses"))
  222.                 k -= 2;
  223.             else if (ends("ies"))
  224.                 setto("i");
  225.             else if (b[k - 1] != 's')
  226.                 k--;
  227.         }
  228.         if (ends("eed")) {
  229.             if (m() > 0)
  230.                 k--;
  231.         } else if ((ends("ed") || ends("ing")) && vowelinstem()) {
  232.             k = j;
  233.             if (ends("at"))
  234.                 setto("ate");
  235.             else if (ends("bl"))
  236.                 setto("ble");
  237.             else if (ends("iz"))
  238.                 setto("ize");
  239.             else if (doublec(k)) {
  240.                 k--;
  241.                 {
  242.                     int ch = b[k];
  243.                     if (ch == 'l' || ch == 's' || ch == 'z')
  244.                         k++;
  245.                 }
  246.             } else if (m() == 1 && cvc(k))
  247.                 setto("e");
  248.         }
  249.     }
  250.     /* step2() turns terminal y to i when there is another vowel in the stem. */
  251.     private final void step2() {
  252.         if (ends("y") && vowelinstem())
  253.             b[k] = 'i';
  254.     }
  255.     /*
  256.      * step3() maps double suffices to single ones. so -ization ( = -ize plus
  257.      * -ation) maps to -ize etc. note that the string before the suffix must
  258.      * give m() > 0.
  259.      */
  260.     private final void step3() {
  261.         if (k == 0)
  262.             return/* For Bug 1 */
  263.         switch (b[k - 1]) {
  264.         case 'a':
  265.             if (ends("ational")) {
  266.                 r("ate");
  267.                 break;
  268.             }
  269.             if (ends("tional")) {
  270.                 r("tion");
  271.                 break;
  272.             }
  273.             break;
  274.         case 'c':
  275.             if (ends("enci")) {
  276.                 r("ence");
  277.                 break;
  278.             }
  279.             if (ends("anci")) {
  280.                 r("ance");
  281.                 break;
  282.             }
  283.             break;
  284.         case 'e':
  285.             if (ends("izer")) {
  286.                 r("ize");
  287.                 break;
  288.             }
  289.             break;
  290.         case 'l':
  291.             if (ends("bli")) {
  292.                 r("ble");
  293.                 break;
  294.             }
  295.             if (ends("alli")) {
  296.                 r("al");
  297.                 break;
  298.             }
  299.             if (ends("entli")) {
  300.                 r("ent");
  301.                 break;
  302.             }
  303.             if (ends("eli")) {
  304.                 r("e");
  305.                 break;
  306.             }
  307.             if (ends("ousli")) {
  308.                 r("ous");
  309.                 break;
  310.             }
  311.             break;
  312.         case 'o':
  313.             if (ends("ization")) {
  314.                 r("ize");
  315.                 break;
  316.             }
  317.             if (ends("ation")) {
  318.                 r("ate");
  319.                 break;
  320.             }
  321.             if (ends("ator")) {
  322.                 r("ate");
  323.                 break;
  324.             }
  325.             break;
  326.         case 's':
  327.             if (ends("alism")) {
  328.                 r("al");
  329.                 break;
  330.             }
  331.             if (ends("iveness")) {
  332.                 r("ive");
  333.                 break;
  334.             }
  335.             if (ends("fulness")) {
  336.                 r("ful");
  337.                 break;
  338.             }
  339.             if (ends("ousness")) {
  340.                 r("ous");
  341.                 break;
  342.             }
  343.             break;
  344.         case 't':
  345.             if (ends("aliti")) {
  346.                 r("al");
  347.                 break;
  348.             }
  349.             if (ends("iviti")) {
  350.                 r("ive");
  351.                 break;
  352.             }
  353.             if (ends("biliti")) {
  354.                 r("ble");
  355.                 break;
  356.             }
  357.             break;
  358.         case 'g':
  359.             if (ends("logi")) {
  360.                 r("log");
  361.                 break;
  362.             }
  363.         }
  364.     }
  365.     /* step4() deals with -ic-, -full, -ness etc. similar strategy to step3. */
  366.     private final void step4() {
  367.         switch (b[k]) {
  368.         case 'e':
  369.             if (ends("icate")) {
  370.                 r("ic");
  371.                 break;
  372.             }
  373.             if (ends("ative")) {
  374.                 r("");
  375.                 break;
  376.             }
  377.             if (ends("alize")) {
  378.                 r("al");
  379.                 break;
  380.             }
  381.             break;
  382.         case 'i':
  383.             if (ends("iciti")) {
  384.                 r("ic");
  385.                 break;
  386.             }
  387.             break;
  388.         case 'l':
  389.             if (ends("ical")) {
  390.                 r("ic");
  391.                 break;
  392.             }
  393.             if (ends("ful")) {
  394.                 r("");
  395.                 break;
  396.             }
  397.             break;
  398.         case 's':
  399.             if (ends("ness")) {
  400.                 r("");
  401.                 break;
  402.             }
  403.             break;
  404.         }
  405.     }
  406.     /* step5() takes off -ant, -ence etc., in context <c>vcvc<v>. */
  407.     private final void step5() {
  408.         if (k == 0)
  409.             return/* for Bug 1 */
  410.         switch (b[k - 1]) {
  411.         case 'a':
  412.             if (ends("al"))
  413.                 break;
  414.             return;
  415.         case 'c':
  416.             if (ends("ance"))
  417.                 break;
  418.             if (ends("ence"))
  419.                 break;
  420.             return;
  421.         case 'e':
  422.             if (ends("er"))
  423.                 break;
  424.             return;
  425.         case 'i':
  426.             if (ends("ic"))
  427.                 break;
  428.             return;
  429.         case 'l':
  430.             if (ends("able"))
  431.                 break;
  432.             if (ends("ible"))
  433.                 break;
  434.             return;
  435.         case 'n':
  436.             if (ends("ant"))
  437.                 break;
  438.             if (ends("ement"))
  439.                 break;
  440.             if (ends("ment"))
  441.                 break;
  442.             /* element etc. not stripped before the m */
  443.             if (ends("ent"))
  444.                 break;
  445.             return;
  446.         case 'o':
  447.             if (ends("ion") && j >= 0 && (b[j] == 's' || b[j] == 't'))
  448.                 break;
  449.             /* j >= 0 fixes Bug 2 */
  450.             if (ends("ou"))
  451.                 break;
  452.             return;
  453.             /* takes care of -ous */
  454.         case 's':
  455.             if (ends("ism"))
  456.                 break;
  457.             return;
  458.         case 't':
  459.             if (ends("ate"))
  460.                 break;
  461.             if (ends("iti"))
  462.                 break;
  463.             return;
  464.         case 'u':
  465.             if (ends("ous"))
  466.                 break;
  467.             return;
  468.         case 'v':
  469.             if (ends("ive"))
  470.                 break;
  471.             return;
  472.         case 'z':
  473.             if (ends("ize"))
  474.                 break;
  475.             return;
  476.         default:
  477.             return;
  478.         }
  479.         if (m() > 1)
  480.             k = j;
  481.     }
  482.     /* step6() removes a final -e if m() > 1. */
  483.     private final void step6() {
  484.         j = k;
  485.         if (b[k] == 'e') {
  486.             int a = m();
  487.             if (a > 1 || a == 1 && !cvc(k - 1))
  488.                 k--;
  489.         }
  490.         if (b[k] == 'l' && doublec(k) && m() > 1)
  491.             k--;
  492.     }
  493.     /**
  494.      * Stem the word placed into the Stemmer buffer through calls to add().
  495.      * Returns true if the stemming process resulted in a word different from
  496.      * the input. You can retrieve the result with
  497.      * getResultLength()/getResultBuffer() or toString().
  498.      */
  499.     public void stem() {
  500.         k = i - 1;
  501.         if (k > 1) {
  502.             step1();
  503.             step2();
  504.             step3();
  505.             step4();
  506.             step5();
  507.             step6();
  508.         }
  509.         i_end = k + 1;
  510.         i = 0;
  511.     }
  512.     /**
  513.      * Test program for demonstrating the Stemmer. It reads text from a a list
  514.      * of files, stems each word, and writes the result to standard output. Note
  515.      * that the word stemmed is expected to be in lower case: forcing lower case
  516.      * must be done outside the Stemmer class. Usage: Stemmer file-name
  517.      * file-name ...
  518.      */
  519.     public static void main(String[] args) {
  520.         char[] w = new char[501];
  521.         Stemmer s = new Stemmer();
  522.         for (int i = 0; i < args.length; i++)
  523.             try {
  524.                 FileInputStream in = new FileInputStream(args[i]);
  525.                 try {
  526.                     while (true)
  527.                     {
  528.                         int ch = in.read();
  529.                         if (Character.isLetter((char) ch)) {
  530.                             int j = 0;
  531.                             while (true) {
  532.                                 ch = Character.toLowerCase((char) ch);
  533.                                 w[j] = (char) ch;
  534.                                 if (j < 500)
  535.                                     j++;
  536.                                 ch = in.read();
  537.                                 if (!Character.isLetter((char) ch)) {
  538.                                     /* to test add(char ch) */
  539.                                     for (int c = 0; c < j; c++)
  540.                                         s.add(w[c]);
  541.                                     /* or, to test add(char[] w, int j) */
  542.                                     /* s.add(w, j); */
  543.                                     s.stem();
  544.                                     {
  545.                                         String u;
  546.                                         /* and now, to test toString() : */
  547.                                         u = s.toString();
  548.                                         /*
  549.                                          * to test getResultBuffer(),
  550.                                          * getResultLength() :
  551.                                          */
  552.                                         /*
  553.                                          * u = new String(s.getResultBuffer(),
  554.                                          * 0, s.getResultLength());
  555.                                          */
  556.                                         System.out.print(u);
  557.                                     }
  558.                                     break;
  559.                                 }
  560.                             }
  561.                         }
  562.                         if (ch < 0)
  563.                             break;
  564.                         System.out.print((char) ch);
  565.                     }
  566.                 } catch (IOException e) {
  567.                     System.out.println("error reading " + args[i]);
  568.                     break;
  569.                 }
  570.             } catch (FileNotFoundException e) {
  571.                 System.out.println("file " + args[i] + " not found");
  572.                 break;
  573.             }
  574.     }
  575. }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值