Spark機器學習算法實操——LinearRegression

任務要求如下:

  • 實現Spark和HIVE與HDFS之間的通信
  • 利用Spark.sql從HIVE中獲取數據,並進行預處理以符合Spark機器學習庫中輸入文件的libsvm格式
  • LinearRegression線性迴歸模型建模
  • 將得到的預測結果寫回HDFS

現在明確了我們的任務目標,就從頭開始進行。

配置Spark和Hive之間的通信

Spark內部可以直接讓SparkContext從hdfs上獲取數據(保證和集羣具有相同的網絡環境)。

//舉例
//創建sparkConf對象,設置spark應用的配置信息
        SparkConf conf = new SparkConf()
                .setAppName("WordCount")
                .setMaster("local");  //spark應用程序要連接的spark集羣的master節點的url,local代表的是本地運行
        //.setMaster("spark://ip:port");

        //創建JavaSparkContext對象
        JavaSparkContext sc = new JavaSparkContext(conf);

        //針對輸入源(hdfs文件、本地文件等)創建一個初始的RDD
        JavaRDD<String> lines = sc.textFile("hfs://master:9000/wordcount.txt");

在Spark1.6開始之後增加了DataSet數據類型,我們注意到通過SparkContext獲得的數據爲RDD類型,而通過SparkSession獲得的數據爲DataSet數據類型。

val sparkSession = SparkSession.builder.
      master("local")
      .appName("example")
      .getOrCreate()
val data = sparkSession.read.text("hdfs://master:9000/wordcount.txt").as[String]

這裏的data是DataSet類型的,如果要轉化爲java可操作的數據類型List或者Array,之後會介紹。因此對於Spark通信hdfs不需要在配置上花費時間。

只需要實現Spark到Hive之間的通信,需要將Hive/conf目錄下的hive-site.xml配置文件複製到Spark/Conf目錄下(這裏假設Hive已經配置好,能和hdfs交互,這裏不贅述);同時還要將JDBC連接器copy到Spark/jars下面,例如mysql-connector-5.4.7.jar類似的,如果連接器版本過高要下載更低版本的。如果出現其他問題,就在Google吧。

Spark從Hive中獲取數據

這裏直接粘一下我的項目代碼

SparkConf conf = new SparkConf().setAppName("sterilizedmilk").setMaster("local");;
        SparkSession spark = SparkSession
                .builder()
                .appName("sterilizedmilk")
                .config(conf)
                .enableHiveSupport()  //支持hive
                .getOrCreate();
        String querySql = "SELECT * FROM myth.sterilizedmilk";
        Dataset<Row> data = spark.sql(querySql);
        data_sterilizedmilk = data.collectAsList();

之前說過Spark封裝了自己的sql函數,跟其他的sql語法一樣,只需要寫成字符串執行就可。查詢到的結果爲DataSet<Row>類型的數據,這個類型自帶了兩個函數:

  1. collect():可以將數據類型返回Array格式
  2. collectAsList():將數據類型返回List格式

獲得的結果可以直接java遍歷操作。下面就需要將數據以Spark.ml算法官方文檔中使用的文件結構存儲。libsvm格式如下:

Label1 para1:value1 para2:value1
Label2 para1:value2 para2:value2

這裏就不沾代碼了,直接按照格式寫入文件就成。

構建LinearRegression模型

這部分沒什麼好說的,直接去看官方文檔給的示例吧!很清楚也很簡潔Spark.ml傳送門

將預測結果寫會HDFS

我這裏選擇的是追加的方式直接將結果寫回hdfs上,也可以保存在服務器本地,再上傳至hdfs(個人覺得麻煩)。

public static void write_prediction_hdfs(List<Row> prediction, String path) throws Exception{

        //獲取precition數據
        int interval = (int)(data_regression.size() * 0.9);

        for(int i = interval; i < data_regression.size(); i++){
            ArrayList<Float> temp = data_regression.get(i);
            temp.add(Float.parseFloat(prediction.get(i-interval).get(2).toString()));
            data_prediction.add(temp);
        }
        //將prediction數據寫入hdfs中
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://master:9000");
        FileSystem fs = FileSystem.get(conf);
        FSDataOutputStream out = fs.create(new Path(path));
        //寫出
        for(int i = 0; i < data_prediction.size(); i++) {
            String re = "";
            for(int j = 0;j<data_prediction.get(i).size();j++) {
                if(j == data_prediction.get(i).size()-1){
                    re = re + data_prediction.get(i).get(j).toString() + "\n";
                }
                else{
                    re = re + data_prediction.get(i).get(j).toString() + " ";
                }
            }
            out.write(re.getBytes("UTF-8"));
        }
        out.close();
    }

可以看到通過追加的方式寫hdfs,就需要配置項,也就是Configuration,這個是hadoop.conf包下的Configuration,通過這個來鏈接hdfs,傳入的path就是hdfs下的目錄,文件將要寫入的位置。for循環裏面的都是我爲了數據格式好看一些做的一些操作,嫌麻煩可以直接把數據每行toString()之後就寫。

 

項目的完整代碼已經提交到Github上,需要自取:傳送門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章