據(jù)分析可視化系統(tǒng)全鏈路實現(xiàn))
每年到了畢設(shè)季總有一批人看到“HadoopDjangoSpark租房數(shù)據(jù)分析可視化”這種題目就頭皮發(fā)麻。很多同學(xué)一方面覺得這個題目技術(shù)棧夠硬寫進(jìn)簡歷里不丟人另一方面又擔(dān)心三四個大數(shù)據(jù)組件疊在一起自己搞不定。這個擔(dān)心我特別理解因為這確實不是一個“套個模板就能跑”的題目但也不是什么高不可攀的東西。說白了這套系統(tǒng)的核心就是一件很簡單的事把一堆租房數(shù)據(jù)收集起來放進(jìn)一個能存大數(shù)據(jù)的倉庫里用一套能快速計算的引擎去分析它再根據(jù)用戶的行為做推薦最后把結(jié)論用一個好看的頁面展示出來。數(shù)據(jù)流向是通的邏輯是順的難點不在單個技術(shù)而在怎么把這些東西串成一條線。這篇文章我會以實際的畢設(shè)項目為例把整套系統(tǒng)的設(shè)計思路、核心模塊拆分、關(guān)鍵代碼實現(xiàn)、環(huán)境聯(lián)調(diào)中的坑全部過一遍。不管你是剛拿到題目還在糾結(jié)怎么起步還是已經(jīng)寫了一半卡在某個環(huán)節(jié)這篇文章都能讓你少走不少彎路。1. 先看清這個項目的整體盤子1.1 題目拆解Hadoop、Django、Spark各自要干什么拿到題目第一件事不是急著寫代碼而是先把題目拆開。這個題目里有三個技術(shù)名詞它們并不是平等的而是各管一攤Hadoop負(fù)責(zé)“存”。原始數(shù)據(jù)量一大Excel和MySQL就撐不住了這時候需要HDFS來存儲海量房源數(shù)據(jù)。畢設(shè)的演示環(huán)境不要求多大但數(shù)據(jù)流向一定要走通。Spark負(fù)責(zé)“算”。Hadoop本身的計算模型偏重批處理寫MapReduce又慢又啰嗦。Spark基于內(nèi)存計算處理結(jié)構(gòu)化數(shù)據(jù)快而且用Python寫起來很順手適合統(tǒng)計區(qū)域均價、戶型分布、價格趨勢這類聚合分析。Django負(fù)責(zé)“掛”。把分析結(jié)果和推薦結(jié)果通過Web頁面展示出來同時管理用戶登錄、收藏、瀏覽記錄這些行為數(shù)據(jù)是整個系統(tǒng)和用戶交互的門面。這套組合在邏輯上是自洽的數(shù)據(jù)量大就上Hadoop存計算復(fù)雜就上Spark算交互展示就交給Django。它既不是單純的大數(shù)據(jù)項目也不是普通的Web管理系統(tǒng)而是把“數(shù)據(jù)倉庫計算引擎Web應(yīng)用”串成了一個完整的業(yè)務(wù)閉環(huán)。1.2 技術(shù)選型為什么這么定很多同學(xué)會問為什么不直接用MySQLSpringBoot或者干脆用Pandas算完再用Flask展示這個問題我在答辯的時候也反復(fù)被問過其實答案并不復(fù)雜。首先畢設(shè)題目是“大數(shù)據(jù)”方向題目里明確出現(xiàn)了Hadoop和Spark這決定了技術(shù)棧必須包含分布式存儲與計算成分這不是說SpringBoot不好而是題目的考點和重點不同。HadoopSpark體現(xiàn)的是大規(guī)模數(shù)據(jù)處理能力Django負(fù)責(zé)的是應(yīng)用層邏輯三者結(jié)合的側(cè)重點在于“數(shù)據(jù)的全鏈路流轉(zhuǎn)”。其次這套組合有天然的互補性。DjangoPython生態(tài)成熟做統(tǒng)計分析、寫推薦算法腳本都方便Spark支持Python API和Django在語言層面統(tǒng)一減少了切換成本。真做起來你會發(fā)現(xiàn)Hadoop負(fù)責(zé)海量數(shù)據(jù)沉淀Spark負(fù)責(zé)把沉淀的數(shù)據(jù)變成指標(biāo)Django負(fù)責(zé)把指標(biāo)變成可交互的產(chǎn)品一條線走下來非常順。還有一個很現(xiàn)實的原因答辯的時候老師一定會問“為什么這么選”。用這套組合能講出道理來——每個組件承擔(dān)獨立角色數(shù)據(jù)流清晰部署有層次感比單一框架的畢設(shè)有更好的展開空間。1.3 系統(tǒng)做出來應(yīng)該長什么樣我按實際項目的經(jīng)驗把功能盤子分成五個模塊你照著這個清單做基本不會漏功能數(shù)據(jù)采集與存儲模塊獲取原始房源數(shù)據(jù)經(jīng)過清洗后寫入HDFS同時將結(jié)構(gòu)化元數(shù)據(jù)同步到MySQL。數(shù)據(jù)分析模塊基于Spark實現(xiàn)區(qū)域均價、戶型分布、價格趨勢、熱門小區(qū)排行等核心指標(biāo)的計算??梢暬故灸K用ECharts展示分析結(jié)果包括柱狀圖、餅圖、折線圖、地圖熱力圖等。智能推薦模塊根據(jù)用戶瀏覽與收藏行為采用協(xié)同過濾推薦算法推薦可能感興趣的房源。用戶管理模塊注冊、登錄、收藏、瀏覽歷史管理這部分由Django直接實現(xiàn)。這五個模塊做下來論文有得寫代碼有得展示答辯PPT也有層次感不會出現(xiàn)“做了個頁面但不知道干嘛”的情況。2. 從數(shù)據(jù)開始采集、清洗與數(shù)倉設(shè)計2.1 數(shù)據(jù)從哪里來三條正規(guī)路子說起數(shù)據(jù)采集很多同學(xué)第一反應(yīng)就是寫爬蟲。我必須提醒一句爬蟲這條路線風(fēng)險很大尤其不能爬那些有明確平臺協(xié)議和數(shù)據(jù)保護(hù)的站點答辯也容易踩雷。做畢設(shè)數(shù)據(jù)來源完全有更穩(wěn)妥的替代方案公開數(shù)據(jù)集一些高校和機構(gòu)提供了脫敏后的房屋租賃數(shù)據(jù)集雖然時效性不一定好但用來做分析完全夠用。合規(guī)的開放接口部分房產(chǎn)信息平臺有開發(fā)者開放接口數(shù)據(jù)內(nèi)容經(jīng)過授權(quán)可以直接調(diào)用。模擬數(shù)據(jù)生成這是最可控的辦法自己寫腳本按真實業(yè)務(wù)規(guī)律生成數(shù)據(jù)比如價格和面積的分布、戶型的占比、區(qū)域的熱度系數(shù)這樣數(shù)據(jù)量可以自由控制跑起Spark來也更有感覺。我手頭這個項目的數(shù)據(jù)就是用模擬腳本生成的生成了一萬條房源記錄覆蓋了城市十個主要區(qū)域。這種做法的好處是數(shù)據(jù)量可以調(diào)整可以在開發(fā)階段用小批量快速調(diào)試演示階段再切到大批量。2.2 數(shù)據(jù)字段與清洗規(guī)則無論數(shù)據(jù)來自哪條路子最后落到HDFS的文件格式都建議統(tǒng)一為CSV或Parquet。CSV的好處是瀏覽器和Excel都能直觀看到排錯方便Parquet在Spark上的查詢效率高但不可讀。畢設(shè)階段用CSV足夠如果時間富余可以再轉(zhuǎn)存一份Parquet。核心字段建議這樣設(shè)計房源ID唯一標(biāo)識字符串類型。小區(qū)名稱字符串清洗時去除首尾空格、特殊符號。區(qū)域城市下轄區(qū)域用于分組統(tǒng)計。價格月租金數(shù)值類型清洗時處理缺失值和異常值。面積平方米數(shù)值類型。戶型臥室數(shù)客廳數(shù)例如“2室1廳”。朝向字符串如“南北通透”“南向”。樓層類型低層/中層/高層方便做樓層偏好分析。租賃方式整租/合租。發(fā)布時間時間戳用于分析供應(yīng)趨勢。關(guān)注熱度數(shù)值可作為房源的受歡迎程度指標(biāo)。清洗規(guī)則是數(shù)據(jù)分析的老本行也是最容易被人忽略但價值最大的一步。原始數(shù)據(jù)里常見的問題是字段缺失、格式不一致、取值范圍不合理。比如價格寫成“面議”或者“2000-2500元/月”這種區(qū)間值都要統(tǒng)一轉(zhuǎn)成數(shù)值面積出現(xiàn)0平米需要剔除或填補區(qū)域字段可能有新舊叫法混雜要映射成同一套標(biāo)準(zhǔn)。我一般是這樣處理的價格缺失的中位數(shù)填充面積小于10或有明確亂碼的直接剔除區(qū)域的同義名稱做一個映射表統(tǒng)一替換。2.3 數(shù)據(jù)存進(jìn)HDFS的目錄結(jié)構(gòu)HDFS的目錄設(shè)計看起來簡單但對后面Spark讀取的便利性影響很大。建議按“數(shù)據(jù)層級業(yè)務(wù)日期”組織目錄比如/rent_hdfs /raw # 原始清洗后數(shù)據(jù) rent_data.csv /processed # Spark處理后的中間結(jié)果 area_price.csv house_type.csv我不建議把HDFS目錄層級設(shè)計得太深因為畢設(shè)的開發(fā)調(diào)試基本在本地環(huán)境進(jìn)行目錄太復(fù)雜只會增加路徑拼接出錯的風(fēng)險。保持兩到三層一眼能看出“原始數(shù)據(jù)在哪、結(jié)果數(shù)據(jù)在哪”就夠了。3. Spark分析引擎讓數(shù)據(jù)說話的核心3.1 離線分析任務(wù)的開發(fā)套路Spark在整套系統(tǒng)里承擔(dān)的是“算”的角色任務(wù)類型屬于離線批處理。實際操作中我發(fā)現(xiàn)很多人一上來就寫復(fù)雜的RDD轉(zhuǎn)換其實大可不必。如果數(shù)據(jù)最終是結(jié)構(gòu)化表格直接用Spark SQLDataFrame API是最舒服的可讀性好統(tǒng)計分析也快。一個典型的分析任務(wù)流程是這樣的通過SparkSession讀取HDFS上的CSV文件。對DataFrame做字段類型轉(zhuǎn)換、過濾異常數(shù)據(jù)。用groupBy、agg等算子完成聚合統(tǒng)計。將結(jié)果寫成CSV或直接寫入MySQL。我用的開發(fā)環(huán)境是Hadoop 3.x Spark 3.xPython版本3.8以上本地模式跑小數(shù)據(jù)量完全夠用不需要在一開始就搭集群。只要代碼最終能在偽分布式模式下讀取HDFS演示時數(shù)據(jù)流就是通的。3.2 核心分析指標(biāo)的計算邏輯我實際項目里做了五個核心指標(biāo)覆蓋了租房分析的各個維度區(qū)域平均租金按區(qū)域分組計算月租金的平均值展示哪個區(qū)最貴、哪里性價比高。戶型分布占比按“幾室?guī)讖d”分組統(tǒng)計數(shù)量反映市場主流供應(yīng)結(jié)構(gòu)。租金價格區(qū)間分布把價格分桶統(tǒng)計每個區(qū)間的房源數(shù)量比如“0-2000”“2000-4000”等用來觀察整體租金分布。熱門小區(qū)TOP10按小區(qū)房源數(shù)量降序排列提取前十名。租金隨發(fā)布時間的變化趨勢按月份聚合均價觀察價格隨時間波動的情況。這些指標(biāo)看著簡單但每一個都能在答辯時說出一段業(yè)務(wù)解釋不是擺一個圖表就結(jié)束。比如區(qū)域均價可以結(jié)合數(shù)據(jù)講講哪個區(qū)域供應(yīng)集中、哪些位置租金中位數(shù)與平均值偏差大。這也是論文里很好的分析素材。3.3 從統(tǒng)計結(jié)果到MySQL的結(jié)果回寫Spark算完的結(jié)果最終要交給Django去展示。這里有兩種做法一種是把Spark結(jié)果落盤成CSVDjango直接讀文件另一種是把結(jié)果寫入MySQLDjango通過ORM查詢。我強烈推薦后者因為Web端查詢靈活用戶按條件篩選時不用每次重新讀文件也便于展示“實時數(shù)據(jù)更新”的效果。回寫MySQL的代碼很簡單用Spark的JDBC寫入即可。需要注意驅(qū)動配置和連接串格式同時表結(jié)構(gòu)要提前在MySQL里建好字段類型盡量和Spark結(jié)果對齊避免類型轉(zhuǎn)換的報錯。df.write.format(jdbc) \ .option(url, jdbc:mysql://localhost:3306/rent_db) \ .option(dbtable, area_price) \ .option(user, root) \ .option(password, your_password) \ .option(driver, com.mysql.cj.jdbc.Driver) \ .mode(overwrite) \ .save()這里有一個小細(xì)節(jié)表名的順序要和你建表時的字段順序?qū)?yīng)上否則有可能出現(xiàn)數(shù)值錯位。我在一開始就吃過這個虧少了對字段名映射結(jié)果“區(qū)域”和“均價”兩列調(diào)換了看起來極其尷尬。4. 智能推薦系統(tǒng)協(xié)同過濾與ALS落地4.1 推薦系統(tǒng)的整體設(shè)計思路推薦系統(tǒng)是很多老師比較關(guān)注的亮點模塊。它不需要做到電商級別那么復(fù)雜但邏輯要完整、要能自圓其說。我這個項目的推薦鏈路是“召回精排”兩段式召回階段根據(jù)用戶當(dāng)前篩選條件區(qū)域、戶型、價格上限從全量房源中篩出候選集這一步主要是縮小計算范圍。精排階段在候選集內(nèi)部使用基于ALS的協(xié)同過濾算法計算用戶對候選房源的預(yù)測評分按評分降序輸出TOP-N。為什么需要召回這一步因為協(xié)同過濾在數(shù)據(jù)稀疏的時候效果很不好。全量房源幾萬條用戶行為記錄又少直接對整個矩陣做預(yù)測結(jié)果基本是亂的。先按業(yè)務(wù)規(guī)則篩一遍把候選集控制在幾百條以內(nèi)再交給ALS排序效果會好很多而且訓(xùn)練速度也更快。4.2 把行為數(shù)據(jù)變成評分?jǐn)?shù)據(jù)ALS的輸入是“用戶ID、房源ID、評分”三列。但真實的用戶行為數(shù)據(jù)里沒有評分只有點擊、收藏、瀏覽這些動作。所以第一步要做的是行為轉(zhuǎn)評分。我的規(guī)則是這樣的收藏房源計5分。點擊查看詳情計3分。直接瀏覽列表頁停留較久計1分。這樣設(shè)計是有道理的收藏代表強意圖點擊代表中等偏好瀏覽代表一般興趣。實現(xiàn)的時候只需要在Django里寫一個信號邏輯用戶執(zhí)行這些操作時自動在行為表中插入或更新評分記錄后面的推薦訓(xùn)練就有數(shù)據(jù)可用。class Behavior(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE) house models.ForeignKey(House, on_deletemodels.CASCADE) behavior_type models.CharField(max_length10) # click/favorite/browse score models.FloatField(default1.0) created_at models.DateTimeField(auto_now_addTrue)這里有個在畢設(shè)中幾乎一定會遇到的尷尬情況系統(tǒng)剛上線用戶很少行為數(shù)據(jù)為零。這種情況下協(xié)同過濾是廢的所以我的處理方案是用戶行為數(shù)據(jù)不足時系統(tǒng)自動退化為“基于熱度的推薦”即按房源關(guān)注熱度、價格合適度、區(qū)域匹配度生成推薦列表當(dāng)行為數(shù)據(jù)積累到一定閾值后才切換到協(xié)同過濾。這個細(xì)節(jié)在答辯時一定要主動講因為它體現(xiàn)的是對真實業(yè)務(wù)問題的認(rèn)知而不是只會調(diào)包。4.3 ALS模型訓(xùn)練與推薦結(jié)果生成使用Spark MLlib里的ALS做矩陣分解訓(xùn)練代碼非常簡潔需要在代碼里指定三列特征列和最大迭代次數(shù)、正則化參數(shù)等超參數(shù)。這些參數(shù)不是越大越好我實測下來10到15輪迭代在小規(guī)模數(shù)據(jù)上已經(jīng)收斂正則化參數(shù)設(shè)在0.1左右效果比較穩(wěn)定具體還需要結(jié)合訓(xùn)練日志觀察。from pyspark.ml.recommendation import ALS from pyspark.ml.evaluation import RegressionEvaluator als ALS( userColuser_id, itemColhouse_id, ratingColrating, coldStartStrategydrop, maxIter12, regParam0.1 ) model als.fit(train_df)訓(xùn)練完成之后需要把模型產(chǎn)出的推薦結(jié)果保存下來供Django查詢。處理辦法是訓(xùn)練結(jié)束后為每個用戶生成TOP10推薦列表寫入一張推薦結(jié)果表中。Django查詢這張表的時候只需要根據(jù)當(dāng)前登錄用戶的ID去取不需要在Web端重新跑一遍模型這樣響應(yīng)速度非???。需要注意ALS有個“冷啟動”問題訓(xùn)練集里沒出現(xiàn)過的新房源模型是感知不到的。所以在推薦結(jié)果表更新的時候我會把新上架房源按熱度插到推薦列表的前幾位保證時效性。這個做法論文里能寫系統(tǒng)層面也能明顯提升推薦結(jié)果的可接受度。5. Django可視化把結(jié)果給用戶看5.1 Django后端與API設(shè)計Django在項目里并不只是模板渲染它還承擔(dān)了數(shù)據(jù)服務(wù)接口的角色。我的設(shè)計是前后端通過JSON交互頁面負(fù)責(zé)渲染接口負(fù)責(zé)提供結(jié)構(gòu)化數(shù)據(jù)。這樣后續(xù)想換前端框架比如換成Vue或React后端代碼可以完全不動。核心接口大概有這么幾個/api/summary/返回總體統(tǒng)計數(shù)據(jù)比如總房源數(shù)、平均租金、區(qū)域數(shù)。/api/area_price/返回區(qū)域均價列表用于柱狀圖。/api/house_type/返回戶型分布用于餅圖。/api/trend/返回價格隨時間變化趨勢用于折線圖。/api/recommend/返回當(dāng)前用戶的推薦房源列表。Django的視圖函數(shù)或類視圖建議統(tǒng)一用JsonResponse返回數(shù)據(jù)注意中文編碼問題設(shè)置json_dumps_params{ensure_ascii: False}否則前端拿到的一串是\uXXXX的轉(zhuǎn)義字符排查起來非常費勁。5.2 可視化大屏的實現(xiàn)要點可視化是大數(shù)據(jù)方向畢設(shè)最直觀的加分項頁面好不好看直接影響答辯印象分。我到最后的實現(xiàn)方案是ECharts Django模板渲染。ECharts使用非常簡單引入JS文件后每個圖表對應(yīng)一個配置項。關(guān)鍵是從Django接口拿到JSON數(shù)據(jù)后動態(tài)塞進(jìn)ECharts的配置里。比如區(qū)域均價圖fetch(/api/area_price/) .then(response response.json()) .then(data { var chart echarts.init(document.getElementById(areaPriceChart)); chart.setOption({ title: { text: 各區(qū)平均租金對比 }, tooltip: {}, xAxis: { data: data.areas }, yAxis: {}, series: [{ name: 均價, type: bar, data: data.prices }] }); });頁面布局上我的建議是采用“大屏風(fēng)”上面一排核心KPI數(shù)字卡片中間幾個主力圖表地圖熱力圖放中間顯眼位置推薦列表放在右側(cè)作為輔助。頁面主色調(diào)可以選用偏深色的底突出數(shù)據(jù)的科技感。這里有個經(jīng)驗不要用太多顏色統(tǒng)一色系再用一兩個高亮色強調(diào)重點區(qū)域即可否則頁面會顯得很“土”。5.3 推薦結(jié)果的展示邏輯推薦結(jié)果不是簡單地列一堆房源卡片而是要讓用戶明白“為什么推薦給我”。我的做法是在每個推薦房源卡片上標(biāo)注推薦理由比如“位于你看過的XX區(qū)域”“價格接近你關(guān)注的區(qū)間”這個細(xì)節(jié)用戶的感知非常好也會成為答辯時的一個亮點。實現(xiàn)上并不復(fù)雜后端返回推薦房源的同時攜帶匹配到的區(qū)域或價格區(qū)間標(biāo)簽前端渲染卡片時放置在標(biāo)題上方。從工程角度看這只是多返回一個字段從產(chǎn)品角度看它讓推薦系統(tǒng)從黑盒變成了可解釋的白盒說服力完全不一樣。對于未登錄用戶推薦接口返回空或返回?zé)衢T房源列表避免因拿不到用戶ID直接報錯。這個兼容邏輯在實際運行中很常見一定要提前處理好。6. 環(huán)境搭建、聯(lián)調(diào)與論文配套6.1 開發(fā)環(huán)境搭建清單很多人的項目不是死在代碼上而是死在環(huán)境搭建上。大數(shù)據(jù)組件版本兼容性問題非常多我把我穩(wěn)定運行的一套組合列出來供你參考操作系統(tǒng)LinuxUbuntu 20.04/22.04或Windows WSL2。Java版本OpenJDK 1.8或11。Hadoop版本3.3.x配置偽分布式模式。Spark版本3.3.x默認(rèn)本地模式運行配置讀取HDFS。Python環(huán)境3.8安裝pyspark、django、pymysql等依賴。MySQL版本8.x。重點提醒一句Hadoop和Spark的版本一定要匹配Spark的官方文檔會標(biāo)明編譯對應(yīng)的Hadoop版本。寧可都選穩(wěn)定版也不要追新否則網(wǎng)上都搜不到對應(yīng)的踩坑資料。安裝順序建議從下往上先裝JDK再裝Hadoop配置環(huán)境變量和SSH免密登錄啟動HDFS后測試數(shù)據(jù)上傳下載然后裝Spark驗證能讀取HDFS文件最后再裝Django和MySQL數(shù)據(jù)庫。每到一個階段就做一次冒煙測試不要把問題積到最后一起爆發(fā)。6.2 部署聯(lián)調(diào)常見問題速查表我把實際運行中遇到過的高頻問題整理成了表格幾乎每個都是踩坑換來的經(jīng)驗建議你直接收藏對照現(xiàn)象可能原因解決辦法Spark連接HDFS超時偽分布式模式下HDFS未啟動或端口配置錯誤檢查start-dfs.sh是否成功執(zhí)行用jps查看NameNode和DataNode進(jìn)程Spark任務(wù)內(nèi)存溢出默認(rèn)executor內(nèi)存太小在spark-submit或代碼中設(shè)置spark.executor.memory2g待在本地跑就調(diào)大本地內(nèi)存MySQL中文亂碼數(shù)據(jù)庫字符集非utf8mb4建庫時指定charsetutf8mb4同時腳本中確保use_unicodeTrueDjango中導(dǎo)入pyspark報錯Spark相關(guān)JAR包環(huán)境變量不對確認(rèn)SPARK_HOME配置正確且使用相同Python解釋器ECharts圖表顯示空白接口返回數(shù)據(jù)格式不對或跨域先直接在瀏覽器訪問接口看是否返回合法JSON再檢查ECharts配置項字段名推薦結(jié)果全是熱門房源用戶行為數(shù)據(jù)不足調(diào)整行為轉(zhuǎn)評分的規(guī)則或檢查訓(xùn)練集是否包含該用戶數(shù)據(jù)其中內(nèi)存溢出是我遇到最多的問題。一開始調(diào)了很大的executor內(nèi)存跑倒是能跑但換到配置較低的機器上就徹底崩潰。后來我調(diào)整了分區(qū)數(shù)和內(nèi)存參數(shù)的組合反而更快更穩(wěn)定。所以說參數(shù)不是越大越好先理解了再調(diào)才不會被表象忽悠。6.3 LW、PPT與講解的準(zhǔn)備經(jīng)驗畢設(shè)交付里除了源碼還有LW、PPT和講解三個部分。很多同學(xué)重代碼輕文檔結(jié)果倒是系統(tǒng)能跑答辯一緊張就講不出東西。這里說說我的經(jīng)驗。LW也就是論文文檔結(jié)構(gòu)上建議按標(biāo)準(zhǔn)軟件工程文檔組織摘要、緒論、需求分析、系統(tǒng)設(shè)計、系統(tǒng)實現(xiàn)、系統(tǒng)測試、總結(jié)展望。重點要寫清楚的是需求分析和系統(tǒng)設(shè)計前者體現(xiàn)你對業(yè)務(wù)的理解后者體現(xiàn)你的技術(shù)架構(gòu)能力。Hadoop、Spark這些組件可以引用一些原理性的描述但不要整段照抄要結(jié)合自己的代碼來寫比如“本系統(tǒng)采用Spark SQL完成區(qū)域均價統(tǒng)計數(shù)據(jù)流如下……”這樣論文查重率也能控制住。PPT最忌諱的就是密密麻麻全是字。一個頁面上只要放一個核心點配合架構(gòu)圖、截圖和關(guān)鍵指標(biāo)即可。講解的重點排在“系統(tǒng)架構(gòu)圖——數(shù)據(jù)流程——推薦算法——可視化效果”這條線上不要一開始就鉆到細(xì)枝末節(jié)里。你要給老師講的是一個完整的、能自洽的故事而不是一組零散的功能點。講解部分如果是錄制視頻要注意兩點一是演示流程要提前排練到流暢尤其是集群啟動和頁面加載的等待時間二是如果中途報錯寧可重錄也不要硬著頭皮繼續(xù)保證成片是“穩(wěn)”的。最后的一點實際心得這套項目做完我最深的感觸是它的難點不在任何一個單一技術(shù)上而在“把數(shù)據(jù)從HDFS流轉(zhuǎn)到Spark再到MySQL最后在頁面上呈現(xiàn)”的全鏈路貫通。你只要把這條鏈路走通把每個環(huán)節(jié)的關(guān)鍵問題想清楚論文、答辯、演示都會順理成章。如果你正在做這個題目我的建議是先別急著裝環(huán)境、寫代碼先把數(shù)據(jù)和業(yè)務(wù)搞明白。一萬條數(shù)據(jù)長什么樣用戶想看什么推薦系統(tǒng)怎么才算有效這些問題想清楚了代碼只是水到渠成的事情。真正卡住你的從來不是某個API不會用而是沒想清楚這一步做完之后下一步要干什么。把鏈路理順剩下的就是耐心調(diào)試的事。