国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【畢業(yè)設計】基于Spark的海量新聞文本聚類(新聞分類)

這篇具有很好參考價值的文章主要介紹了【畢業(yè)設計】基于Spark的海量新聞文本聚類(新聞分類)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

0 前言

?? Hi,大家好,這里是丹成學長的畢設系列文章!

?? 對畢設有任何疑問都可以問學長哦!

這兩年開始,各個學校對畢設的要求越來越高,難度也越來越大… 畢業(yè)設計耗費時間,耗費精力,甚至有些題目即使是專業(yè)的老師或者碩士生也需要很長時間,所以一旦發(fā)現(xiàn)問題,一定要提前準備,避免到后面措手不及,草草了事。

為了大家能夠順利以及最少的精力通過畢設,學長分享優(yōu)質畢業(yè)設計項目,今天要分享的新項目是

?? 基于Spark的海量新聞文本聚類

??學長這里給一個題目綜合評分(每項滿分5分)

  • 難度系數(shù):4分
  • 工作量:4分
  • 創(chuàng)新點:3分

?? 選題指導, 項目分享:

https://gitee.com/yaa-dc/BJH/blob/master/gg/cc/README.md

1 項目介紹

在大數(shù)據(jù)開發(fā)領域,Spark的大名如雷貫耳,其RDD(彈性分布式數(shù)據(jù)集)/DataFrame的內存數(shù)據(jù)結構,在機器學習“迭代”算法的場景下,速度明顯優(yōu)于Hadoop磁盤落地的方式,此外,Spark豐富的生態(tài)圈也使得使用它為核心能夠構建一整套大數(shù)據(jù)開發(fā)系統(tǒng)。

今天學長將采用Spark,利用tf-idf作為文本特征,k-means算法進行聚類。

各工具版本信息如下:

  • Spark 2.0.0
  • scala 2.11.8
  • java 1.8
  • hanlp 1.5.3

2 實現(xiàn)流程

所采用的數(shù)據(jù)集是已經(jīng)預處理過的,每個類別的文件都按照1,2,3這樣的數(shù)據(jù)開頭,這里的1,2,3就代表類別1,類別2,類別3.這樣會遇到一個問題,也是該博客實現(xiàn)過程中的一個bug,類別10的開頭第一個字母也是‘1’,導致類別1的判定是存在爭議的。但為了省事,筆者這里就只用其中的9類文本作為聚類文本,由已知標簽,從而判斷聚類效果。

參考中的博客采用的Spark版本偏老,為Spark1.6,現(xiàn)在Spark的版本已經(jīng)邁進了2代,很多使用方法都不建議了,比如SQLContext,HiveContext和java2scala的一些數(shù)據(jù)結構轉換。本文立足2.0版本的spark,將其中過時的地方代替,更加適合新手入門上手。

3 開發(fā)環(huán)境

開發(fā)環(huán)境采用idea+maven(雖然SBT在spark業(yè)界更加流行)

下面是學長的maven配置,放在pom.xml文件中:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>HanLP</groupId>
    <artifactId>myHanLP</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spark.version>2.0.0</spark.version>
        <scala.version>2.11</scala.version>
    </properties>

    <dependencies>
        <!-- scala環(huán)境,有了spark denpendencies后可以省略 -->
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.8</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-compiler</artifactId>
            <version>2.11.8</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-reflect</artifactId>
            <version>2.11.8</version>
        </dependency>
        <!-- 日志框架 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!-- 中文分詞框架 -->
        <dependency>
            <groupId>com.hankcs</groupId>
            <artifactId>hanlp</artifactId>
            <version>portable-1.5.3</version>
        </dependency>
        <!-- Spark dependencies -->
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-streaming_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-hive_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-mllib_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

其中需要注意的有兩個地方,第一個地方是scala.version,不要具體寫到2.11.8,這樣的話是找不到合適的spark依賴的,直接寫2.11就好。第二個地方是maven-scala-plugin,這個地方主要是為了使得項目中java代碼和scala代碼共存的,畢竟它們倆是不一樣的語言,雖然都能在jvm中跑,但編譯器不一樣呀…所以這個地方非常重要.

4 java目錄功能介紹

java目錄下的文件主要有兩個功能:

  • 測試Hanlp
  • 轉換編碼、合并文件

測試hanlp工具,這是個開源的java版本分詞工具,文件中分別測試了不同的分詞功能。另一個是將所有文件從GBK編碼模式轉換成UTF-8,再將這些小文件寫到一個大文件中。轉換編碼是為了文件讀取順利不報編碼的錯誤。大文件是為了提高Spark或Hadoop這類工具的效率,這里涉及到它們的一些實現(xiàn)原理,簡單來說,文件輸入到Spark中還會有分塊、切片的操作,大文件在這些操作時,效率更高。

5 scala目錄功能介紹

scala目錄下總共有4個子目錄,分別是用來測試scala編譯運行是否成功,調用Spark MLlib計算tf-idf,計算TF-IDF再利用K-means聚類,工具類。這里的工具類是原博客作者設計的,設計的目的是確定Spark是在本地測試,還是在集群上火力全來跑,并且適用于Window系統(tǒng)。因為我去掉了其封裝的SQLContext(已不建議使用),所以這個工具類在我Linux操作系統(tǒng)下意義也不是很大…

5.1 求TF-IDF

求TF-IDF采用SparkSession替代SparkContext,如下:

package test_tfidf

import org.apache.spark.ml.feature.{HashingTF, IDF, Tokenizer}
import org.apache.spark.sql.SparkSession
//import utils.SparkUtils
/**
  *測試Spark MLlib的tf-idf
  * Created by zcy on 18-1-4.
  */
object TFIDFDemo {
  def main(args: Array[String]) {
    val spark_session = SparkSession.builder().appName("tf-idf").master("local[4]").getOrCreate()
    import spark_session.implicits._ // 隱式轉換
    val sentenceData = spark_session.createDataFrame(Seq(
      (0, "Hi I heard about Spark"),
      (0, "I wish Java could use case classes"),
      (1, "Logistic regression models are neat")
    )).toDF("label", "sentence")

    // 分詞
    val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
    println("wordsData----------------")
    val wordsData = tokenizer.transform(sentenceData)
    wordsData.show(3)
    // 求TF
    println("featurizedData----------------")
    val hashingTF = new HashingTF()
      .setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(2000) // 設置哈希表的桶數(shù)為2000,即特征維度
    val featurizedData = hashingTF.transform(wordsData)
    featurizedData.show(3)
    // 求IDF
    println("recaledData----------------")
    val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
    val idfModel = idf.fit(featurizedData)
    val rescaledData = idfModel.transform(featurizedData)
    rescaledData.show(3)
    println("----------------")
    rescaledData.select("features", "label").take(3).foreach(println)
  }
}

上面TF轉換特征向量的代碼設置了桶數(shù),即特征向量的維度,這里將每個文本用2000個特征向量表示。

5.2 調用K-means模型

// Trains a k-means model.
println("creating kmeans model ...")
val kmeans = new KMeans().setK(k).setSeed(1L)
val model = kmeans.fit(rescaledData)
// Evaluate clustering by computing Within Set Sum of Squared Errors.
println("calculating wssse ...")
val WSSSE = model.computeCost(rescaledData)
println(s"Within Set Sum of Squared Errors = $WSSSE")

5.3 評價方式

假設最終得到的文件和預測結果如下:

val t = List(
    ("121.txt",0),("122.txt",0),("123.txt",3),("124.txt",0),("125.txt",0),("126.txt",1),
    ("221.txt",3),("222.txt",4),("223.txt",3),("224.txt",3),("225.txt",3),("226.txt",1),
    ("421.txt",4),("422.txt",4),("4.txt",3),("41.txt",3),("43.txt",4),("426.txt",1)

文件名的第一個字符是否和聚類類別一致,統(tǒng)計結果來判斷,是否聚類成功,最終得到整體的聚類準確率,這里提供demo例子如下:

package test_scala

import org.apache.spark.Partitioner
import utils.SparkUtils
/**
  * Created by zcy on 18-1-4.
  */
object TestPartition {
  def main(args: Array[String]): Unit ={
    val t = List(
      ("121.txt",0),("122.txt",0),("123.txt",3),("124.txt",0),("125.txt",0),("126.txt",1),
      ("221.txt",3),("222.txt",4),("223.txt",3),("224.txt",3),("225.txt",3),("226.txt",1),
      ("421.txt",4),("422.txt",4),("4.txt",3),("41.txt",3),("43.txt",4),("426.txt",1)
    ) // 文檔開頭代表類別,后一個數(shù)字代表預測類型
    val sc = SparkUtils.getSparkContext("test partitioner",true) //本地測試:true

    val data = sc.parallelize(t)
    val file_index = data.map(_._1.charAt(0)).distinct.zipWithIndex().collect().toMap
    println("file_index: " + file_index) // key:begin of txt, value:index
    val partitionData = data.partitionBy(MyPartitioner(file_index))

    val tt = partitionData.mapPartitionsWithIndex((index: Int, it: Iterator[(String,Int)]) => it.toList.map(x => (index,x)).toIterator)
    println("map partitions with index:")
    tt.collect().foreach(println(_)) // like this: (0,(421.txt,4))
    // firstCharInFileName , firstCharInFileName - predictType

    val combined = partitionData.map(x =>( (x._1.charAt(0), Integer.parseInt(x._1.charAt(0)+"") - x._2),1) )
      .mapPartitions{f => var aMap = Map[(Char,Int),Int]();
        for(t <- f){
          if (aMap.contains(t._1)){
            aMap = aMap.updated(t._1,aMap.getOrElse(t._1,0)+1)
          }else{
            aMap = aMap + t
          }
        }
        val aList = aMap.toList
        val total= aList.map(_._2).sum
        val total_right = aList.map(_._2).max
        List((aList.head._1._1,total,total_right)).toIterator
        //       aMap.toIterator //打印各個partition的總結
      }
    val result = combined.collect()
    println("results: ")
    result.foreach(println(_)) // (4,6,3) 類別4,總共6個,3個正確
    for(re <- result ){
      println("文檔"+re._1+"開頭的 文檔總數(shù):"+ re._2+",分類正確的有:"+re._3+",分類正確率是:"+(re._3*100.0/re._2)+"%")
    }
    val averageRate = result.map(_._3).sum *100.0 / result.map(_._2).sum
    println("平均正確率為:"+averageRate+"%")
    sc.stop()
  }
}

case class MyPartitioner(file_index:Map[Char,Long]) extends Partitioner{
  override def getPartition(key: Any): Int = key match {
    case _ => file_index.getOrElse(key.toString.charAt(0),0L).toInt //將value轉換成int
  }
  override def numPartitions: Int = file_index.size
}

6 聚類結果

最終,在學長本地Spark偽集群環(huán)境下,用4個進程模擬4臺主機,輸出結果如下:

基于spark的畢業(yè)設計,大數(shù)據(jù),畢業(yè)設計,spark,新聞分類,文本聚類

從整個運行結果來看,正確率還是很高的,值得信賴,但和參考大佬的論文比,某些類別還是不夠準確,畢竟k-means算法有一定的隨機性,這種誤差我們還是可以接受的。并且從整體運行時間上來說,真的非??欤ü烙嬙谑畮酌耄?,這個時間還包括了啟動Spark,初始化等等過程,和python處理相比,不僅高效,還更加可靠。強推…文章來源地址http://www.zghlxwxcb.cn/news/detail-659906.html

7 最后

到了這里,關于【畢業(yè)設計】基于Spark的海量新聞文本聚類(新聞分類)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包