您好,登錄后才能下訂單哦!
前言
最近一段時間都在處理電影領域的數據, 而電影票房預測是電影領域數據建模中的一個重要模塊, 所以我們針對電影數據做了票房預測建模.
前期工作
一開始的做法是將這個問題看待成回歸的問題, 采用GBDT回歸樹去做. 訓練了不同殘差的回歸樹, 然后做集成學習. 考慮的影響因子分別有電影的類型, 豆瓣評分, 導演的 影響力, 演員的影響力, 電影的出品公司. 不過預測的結果并不是那么理想, 準確率為真實值的0.3+/-區間情況下的80%, 且波動性較大, 不容易解析.
后期的改進
總結之前的失敗經驗, 主要歸納了以下幾點:
1.影響因子不夠多, 難以建模
2.票房成績的區間較大(一百萬到10億不等),分布不均勻, 大多數集中與億級, 所以不適合采用回歸方法解決.
3.數據樣本量比較少, 不均勻, 預測百萬級的電影較多, 影響預測結果
后期, 我們重新規范了數據的輸入格式, 即影響因子, 具體如下:
第一行: 電影名字
第二行: 電影票房(也就是用于預測的, 以萬為單位)
第三行: 電影類型
第四行: 片長(以分鐘為單位)
第五行:上映時間(按月份)
第六行: 制式( 一般分為2D, 3D, IMAX)
第七行: 制作國家
第八行: 導演影響 (以導演的平均票房成績為衡量, 以萬為單位 )
第九行: 演員影響 ( 以所有演員的平均票房成績為衡量, 以萬為單位 )
第十行:制作公司影響 ( 以所有制作公司的平均票房成績為衡量, 以萬為單位 )
第十一行: 發行公式影響 ( 以所有制作公司的平均票房成績為衡量,以萬為單位 )
收集了05-17年的來自中國,日本,美國,英國的電影, 共1058部電影. 由于處理成為分類問題, 故按將電影票房分為以下等級:
在構建模型之前, 先將數據處理成libsvm格式文件, 然后采用隨機森林模型訓練.
隨機森林由許多的決策樹組成, 因為這些決策樹的形成采用隨機的策略, 每個決策樹都隨機生成, 相互之間獨立.模型最后輸出的類別是由每個樹輸出的類別的眾數而定.在構建每個決策樹的時候采用的策略是信息熵, 決策樹為多元分類決策樹.隨機森林的流程圖如下圖所示:
隨機森林是采用spark-mllib提供的random forest, 由于超過10億的電影的數據相對比較少, 為了平衡各數據的分布, 采用了過分抽樣的方法, 訓練模型的代碼如下:
public void predict() throws IOException{ SparkConf conf = new SparkConf().setAppName("SVM").setMaster("local"); conf.set("spark.testing.memory", "2147480000"); SparkContext sc = new SparkContext(conf); SQLContext sqlContext = new SQLContext(sc); // Load and parse the data file, converting it to a DataFrame. DataFrame trainData = sqlContext.read().format("libsvm").load(this.trainFile); DataFrame testData = sqlContext.read().format("libsvm").load(this.testFile); // Index labels, adding metadata to the label column. // Fit on whole dataset to include all labels in index. StringIndexerModel labelIndexer = new StringIndexer() .setInputCol("label") .setOutputCol("indexedLabel") .fit(trainData); // Automatically identify categorical features, and index them. // Set maxCategories so features with > 4 distinct values are treated as continuous. VectorIndexerModel featureIndexer = new VectorIndexer() .setInputCol("features") .setOutputCol("indexedFeatures") .setMaxCategories(4) .fit(trainData); // Split the data into training and test sets (30% held out for testing) // DataFrame[] splits = trainData.randomSplit(new double[] {0.9, 0.1}); // trainData = splits[0]; // testData = splits[1]; // Train a RandomForest model. RandomForestClassifier rf = new RandomForestClassifier() .setLabelCol("indexedLabel") .setFeaturesCol("indexedFeatures") .setNumTrees(20); // Convert indexed labels back to original labels. IndexToString labelConverter = new IndexToString() .setInputCol("prediction") .setOutputCol("predictedLabel") .setLabels(labelIndexer.labels()); // Chain indexers and forest in a Pipeline Pipeline pipeline = new Pipeline() .setStages(new PipelineStage[] {labelIndexer, featureIndexer, rf, labelConverter}); // Train model. This also runs the indexers. PipelineModel model = pipeline.fit(trainData); // Make predictions. DataFrame predictions = model.transform(testData); // Select example rows to display. predictions.select("predictedLabel", "label", "features").show(200); // Select (prediction, true label) and compute test error MulticlassClassificationEvaluator evaluator = new MulticlassClassificationEvaluator() .setLabelCol("indexedLabel") .setPredictionCol("prediction") .setMetricName("precision"); double accuracy = evaluator.evaluate(predictions); System.out.println("Test Error = " + (1.0 - accuracy)); RandomForestClassificationModel rfModel = (RandomForestClassificationModel)(model.stages()[2]); // System.out.println("Learned classification forest model:\n" + rfModel.toDebugString()); DataFrame resultDF = predictions.select("predictedLabel"); JavaRDD<Row> resultRow = resultDF.toJavaRDD(); JavaRDD<String> result = resultRow.map(new Result()); this.resultList = result.collect(); for(String one: resultList){ System.out.println(one); } }
下面為其中一個的決策樹情況:
Tree 16 (weight 1.0): If (feature 10 in {0.0}) If (feature 48 <= 110.0) If (feature 86 <= 13698.87) If (feature 21 in {0.0}) If (feature 54 in {0.0}) Predict: 0.0 Else (feature 54 not in {0.0}) Predict: 1.0 Else (feature 21 not in {0.0}) Predict: 0.0 Else (feature 86 > 13698.87) If (feature 21 in {0.0}) If (feature 85 <= 39646.9) Predict: 2.0 Else (feature 85 > 39646.9) Predict: 3.0 Else (feature 21 not in {0.0}) Predict: 3.0 Else (feature 48 > 110.0) If (feature 85 <= 15003.3) If (feature 9 in {0.0}) If (feature 54 in {0.0}) Predict: 0.0 Else (feature 54 not in {0.0}) Predict: 2.0 Else (feature 9 not in {0.0}) Predict: 2.0 Else (feature 85 > 15003.3) If (feature 65 in {0.0}) If (feature 85 <= 66065.0) Predict: 3.0 Else (feature 85 > 66065.0) Predict: 2.0 Else (feature 65 not in {0.0}) Predict: 3.0 Else (feature 10 not in {0.0}) If (feature 51 in {0.0}) If (feature 85 <= 6958.4) If (feature 11 in {0.0}) If (feature 50 <= 1.0) Predict: 1.0 Else (feature 50 > 1.0) Predict: 0.0 Else (feature 11 not in {0.0}) Predict: 0.0 Else (feature 85 > 6958.4) If (feature 5 in {0.0}) If (feature 4 in {0.0}) Predict: 3.0 Else (feature 4 not in {0.0}) Predict: 1.0 Else (feature 5 not in {0.0}) Predict: 2.0 Else (feature 51 not in {0.0}) If (feature 48 <= 148.0) If (feature 0 in {0.0}) If (feature 6 in {0.0}) Predict: 2.0 Else (feature 6 not in {0.0}) Predict: 0.0 Else (feature 0 not in {0.0}) If (feature 50 <= 4.0) Predict: 2.0 Else (feature 50 > 4.0) Predict: 3.0 Else (feature 48 > 148.0) If (feature 9 in {0.0}) If (feature 49 <= 3.0) Predict: 2.0 Else (feature 49 > 3.0) Predict: 0.0 Else (feature 9 not in {0.0}) If (feature 36 in {0.0}) Predict: 3.0 Else (feature 36 not in {0.0}) Predict: 2.0
后記
該模型預測的平均準確率為80%, 但相對之前的做法規范了很多, 對結果的解析也更加的合理, 不過如何增強預測的效果, 可以考慮更多的因子, 形如:電影是否有前續;電影網站的口碑指數;預告片的播放量;相關微博的閱讀數;百度指數等;
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。