The Renaissance of Mobile Web – Physical Web

thumb_IMG_1788_1024

“What if the world behaved like the web?”, This question was asked by Scott JensOn on the stage of session “The Physical Web: Make It So” in the Google I/O 2016, he is the project leader of Physical Web and Chrome in Google, as a long term web technology and mobile web enthusiast, this value proposition is very powerful and exciting to me, because it opens up the whole growing IoT market to web developers like me.

Actually, I know this project since its beginnings several years ago, IoT was the hottest topic at that time, there were countless Kickstarter, Indiegogo and many other crowdsourcing projects everywhere, it just likes the booming age of native mobile apps since 2010, everyone were desperately to build their own mobile apps at that time, but just as a rebellious boy I am, I did not choose that path, because I do believe that the open web and HTML5 should win the future of mobile eventually instead of the native one(tell you what, it is happening), now, in the dawn of the IoT, I also believe in that the open web will win in this field too, hopefully, with Physical Web, it is time for web developers to do something with open web technologies now, I will share what all I know about this project so far and what we as a web developer can do now in this series articles.

First of all, we should be bare one thing in mind, the Physical Web is just one of many other solutions under WoT(Web of Things) umbrella, it does not equal to the whole of WoT, the concept of WoT was proposed by W3C in order to address the frustration of interoperability across different IoT platforms, it wants to create a standard protocol to make data exchange and system integration among different platforms more smoothly, and you know, by using HTTP.

For now, when we talk about the Physical Web, we are talking about a new kind of BLE beacon and that kind beacons’ communication protocol are based on an open source project called Eddystone which is released and maintained by Google’s Physical Web project team.

13305181_10153667521313595_2332053475097400521_oThe main difference between a traditional beacon and Eddystone compatible beacon is that an Eddystone compatible beacon broadcasts a URL instead of an obscure UUID string. The URL is the fundamental building block of the web, it offers a remarkable flexibility of expression, with it we can do many awesome things when users’ mobile device received a broadcasting message from an Eddystone beacons, for example we can use broadcasting URLs to lead users to a simple product or event’s landing-page or we can bring users to a fully interactive progressive web application(PWA), we can even offer a deep link to link users into a specific app or specific content inside apps.

 

The most important thing is that we can accomplish these amazing things without a native app, the only thing we need is a browser that supports Web Bluetooth specification in your mobile device, for now, we have “Chrome for Android”, “Chrome for Android Beta”, “Chrome for Android Dev”, “Chrome for iOS”, “Opera for Android Beta” and “Samsung S Browser”.(Where are you? Firefox?)

Before the Physical Web, if we want to do something special with traditional beacons, for example, an O2O promotion campaign, we need to do a lot of things, the most difficult and nonsense one is that we have to develop a native app and require users to download this dedicated app in order to decipher the obscure UUID(ex. f7826da6-4fa2-4e98-8024-bc5b71e0893e) string that are broadcasting by traditional beacons, these UUIDs do not have any useful meaning until you send it back to your backend service to match it with data that is stored in your database.

Ironically, before you can leverage beacon’s power to do a novel O2O campaign to attract users to your product or service, you have to spend a lot of campaign budget to find users to download the dedicated app for your O2O campaign in order to decipher those meaningless UUIDs, and that app can not do anything other than to receive your dedicated beacons’ broadcasting message.

13308435_10153667519598595_6601818795220317314_oThat is why the Physical Web comes to the scene, as I said before, We will no longer need a dedicated native app to interpret a received message from a beacon, what all we need is a Web Bluetooth enabled browser in your mobile device such as Chrome for Android and Opera for Android. Then we can use these browsers to receive the message, URLs, broadcasting by the surround Eddystone compatible beacons, by using these URLs we can lead users to a simple product/service landing-page or offer users a cutting-edge Progressive Web Application(PWA) or even direct them to specific page inside a native app.

 

13308463_10153667523438595_4438404961686044493_oLet me make a brief summary, First, Physical Web is the bridge between physical things and the web, it allows us to walk up to anything and just use it. Second, it is based on the open protocol specification Eddystone, the data Eddystone compatible beacon broadcasts are semantic and readable URLs. Second, by following Eddystone specification the beacon are also compatible with Apple’s iBeacon, Furthermore, there are already 30+ manufacturers in the world making Eddystone compatible beacons now, Last but not least, by the end of 2016, an Eddystone beacon’s battery power can be last for one decade. This is so cool! Is it not? In the next article I will show you how to set up your mobile device and Eddystone compatible beacons to see how it works in the real world, stay tuned.

Posted in Uncategorized | Leave a comment

The Renaissance of Mobile Web – The Dawn

thumb_IMG_1893_1024

OK, this is not an article trying to ignite the debate of which one is better between native app and mobile web again, I am just trying to share some my observations about the status quo of this mobile-first world, because it is getting more clearer in recent years that this is not a zero-sum game between native app and HTML5 mobile web, let’s figure it out.

I read an article this day, the article’s title is “Goodbye, Native Mobile Apps”. it is wrote by Evan Ratliff & Jefferson Rabb, they are the founders of Atavist, A publishing and storytelling platform. In that article they explained why they revamped all of their service from scratch by HTML5 and totally made the native solution obsoleted. They proposed several key points about this decision.

First, Driving users from mobile web or social media into a native app proved to be a highly challenging operation. Today, the social media such as Facebook, Twitter and Snapchat are on the top of conversion funnel, there are several methods that can lead users from a mobile web or social media to native app. The worst one, you can put a full screen interstitial ads in front of your readers and content to urge readers to download your native app in order to get the same content that they can read right now. The better one, you can try to use “available on the app store” banners to occupy the real estate even though Google released a blog claiming that this mechanism does not work. The ultimate solution, “Deep Linking”, This is once the promised solution to link user directly into specific articles in an app when they tapped your shared content on Facebook or other native apps. I am not a native app developer but the authors claimed deep linking is not as effective as it promised and it is difficult to implement well to give users a good experience.

Second, By using the modern web technologies we have today, designers and publishers can produce a superior reading and interactive experience for their audiences, if Atavist wants to achieve the design and experience to match its web counterpart, it requires a tremendous amount of native code work.

Third, Authors say that their service can reach 50 ~ 100 times larger readership on the desktop and mobile web than what they could in their native app. According to Morgan Stanley’s latest research report, it shows that mobile browser traffic is two times bigger than native app traffic, Morgan Stanley’s research is focused on unique visitors of mobile web. In contrast to Morgan Stanley’s methodology, comScore also released its latest “US Mobile App Report” this week and its research is focused on the time spent in mobile, in that report, comScore showed that almost 87% of all time spent on mobile in the USA that was spent in native mobile apps.

In my opinion, native app and mobile web are in an intricate coexistence era, none of them can defeat soundly one another. To be frankly, I am the loyal supporter of HTML5 mobile web, it is not only because my first startup’s core product were based on it but also the profound changes are happening in this field day by day.

I joined Google I/O 2016 at its headquarter in Mountain View last week, there were almost 30+ mobile web related sessions across this three days developer carnival. The core concept of these 30+ web-related sessions are all around “Progressive Web Apps”, What is a Progressive Web App?OK! In a very high level overview, it can work offline by using Service Worker, it can be added to home screen by a JSON file called “manifest.json”, it can publish notifications just like its native counterpart to keep user re-engagement, it is instant loading by using some cutting-edge techniques such as Facebook Instant Article and Google Accelerated Mobile Page.

In the following article, I will write what I have learned in this year’s Google IO 2016, and I will introduce you a promised technology called Physical Web to you, please stay tuned.

Posted in Uncategorized | Leave a comment

ETL?真的只是略懂(一)

bdt303-construct-your-etl-pipeline-with-aws-data-pipeline-amazon-emr-and-amazon-redshift-aws-reinvent-2014-2-638

一樣從這篇由Twitter資料科學家Robert Chang所撰寫的文章做衍生,今天我想來分享一下什麼是ETL?如同他在文章中所提到的,要在公司內導入資料驅動的文化,首先要做的是先去仔細的審視公司目前所處的成長階段在哪裡?然後再決定現在公司要在資料科學上做什麼投資,假設當一間公司正處於新創階段,通常這時不會有太多的資料可以進行分析,這時該思考的或許就不應該是資料分析本身,而是要去思考如何替未來即將要進行的資料分析去進行打地基的工作,這階段,ETL就是資料科學地基的一部分。

那究竟ETL是什麼呢?ETL是Extract, Transform and Load的字首縮寫,ETL本身並不是某一個特定的技術而是一種程序與mindset,一種如何從異質或同質資料中源萃取出資料,並依照公司商業上的需求去轉換成適當的格式與結構,並將這些轉換後的資料存放在安全且符合成本效益的儲存載體中,讓這些資料能夠在未來便於查詢與分析去為公司創造經濟價值的程序。

ETL絕對需要強大的技術力才能被實踐出來,而且並非一人之力可為之,在傳統上有許多大型軟體公司會為ETL提供完善(?)的解決方案,甚至ETL解決方案的本身就是很多軟體公司的主要商業模式,但隨著IaaS的興起,例如AWS與Azure,有愈來愈多的公司開始使用IaaS所提供的各項微服務來去作為他們ETL的解決方案,像我們公司就是將AWS多項Web Service組構成我們的ETL。

ETL中的E代表Extract,在很多研究案例中,E可以說是決定ETL成敗的主要因素,在這個過程中,進行ETL的資料基礎建設要有能力根據商業邏輯去許多不同的資料源取得資料,通常從這些資料源取回的資料可以概略分為結構性(XML、JSON、DB SQL、CSV…etc)與非結構性資料(網頁爬蟲結果、圖片、音頻與影像檔案…etc)兩種,並在要傳遞到ETL下一個階段之前,要將這些格式與結構相異的資料轉換成一致的資料格式,並根據相對應的領域知識規則去驗證所取得資料的正確性以及完整性,如果可能的話,ETL在這一階段還要能夠在資料驗證失敗後去完全或部分拒絕錯誤資料源所提供的資料,並通知資料源進行修正與紀錄。

在Extract(E)之後的就是Transform(T),在這個階段最重要的任務是對上一個階段傳入的資料進行資料清理(Data Cleansing),盡所有可能避免將格式不正確的資料傳入最後的目標儲存載體中。在這個階段,要對哪些資料進行清理是要依據公司的商業邏輯需求來進行的,就我過往實務經驗來說有以下幾種資料清理的工作是經常在執行的:

  • 當異質的資料源在字元集的支援度上不一時,這時該如何進行資料的填補或濾除? 
  • 當不同資料源使用的字元編碼不一時,像是當來自各個不同資料源的資料中包含了BIG5與UTF-8甚至更多其他的字元編碼時,究竟該採用哪一個編碼格式作為自家ETL的通用編碼? 假設採用UTF-8,那偵測資料集的字元編碼並對其進行編碼轉換就是一個很大的工。 
  • 數字與型態列舉間的轉換:這絕對是在做資料清理過程中經常會碰到的問題,像我在開發廣告系統的時候,不同的廣告平台在族群鎖定參數上使用的方式就會有很大的差異,以男女性別為例子,有些廣告系統是用1、2、3來代表男生、女生與不分性別,而另外一個廣告系統卻有可能會使用male、female與all來代表,這還好,講個更複雜的情況,Facebook的廣告系統在投放廣告時,對於要鎖定的族群年齡可以細分到每一歲,例如18-19以及20-22歲,但是Google的AdWords廣告系統在進行廣告受眾年齡鎖定的時候卻只能預設好的年齡範圍來設定,例如《18~23歲》,類似這樣的資料不一致性在我嘗試將我們公司所有廣告操作的歷史資料整理進入data warehouse要去做Machine Learning的時候造成很大的困擾,必須透過與我的資料科學家們進行討論後去做出一些取捨。 
  • 當要寫入data warehouse的資料是需要透過將單一或多個資料源資料去混搭並計算後的新資料時,例如要計算出跨資料源資料的敘述統計量與機率分配,或是要做簡單的運算後去衍生出對公司經營上更具經濟價值的數據,像是我們這種數位廣告公司很看重CPC、CPM、CPI、CPA與CPV等等績效指標。 
  • 有很多資料在進資料庫或是資料倉儲前會根據商業上的需求而事先做些樞紐(Pivoting)或移調(Tranpose)的變換,將而二維資料的資料矩陣做行與列(反之亦然)的調整去從資料中推演出更多的洞見。 
  • 另外我也經常遇到資料源包含必須在資料擷取回來後進行切割與分離的狀況,像是原始資料源中某些資料欄位是用逗號或是特殊符號去組成一個字串去表示一組連續的相關的資料,像是我就看過有人用”|”去儲存購物車中的產品清單商業鍵,有點像是”product_126453|product_432432|product_349473..”這樣,這時為了能夠跟進銷存資料對應在一起,我必須在將資料打入資料倉儲前把字串拆開成為個別的欄位去儲存。

當然除了上面講到的幾個例子,還有很多不勝枚舉的工作會發生在這個Transform的階段裡,像是去除重複資料與填充缺失的資料甚至要重新去建立與原始資料集完全不同的Surrogate Key也是有可能發生的。

最後,就是ETL中的Load了,其實最簡單的解釋就是如何將清洗過的資料儲存進設計好的目標儲存載體裡,說上去簡單,但這個階段在架構設計上也有非常多的策略性思考要進行,像是資料寫入是採用覆寫的方式還是累增的方式?歷史資料存放的Time Window為何?資料查詢與分析的即時性為何?要即時性BI,那就跑一堆批次程序去整理raw data然後把產生出來具有洞見的資料寫入AWS RDS或是MongoDB中供前端UI查詢,如果是不需要即時性資料,那是否為了省些成本先打入AWS S3中,甚至是壓縮一下直接塞進AWS Glacier?更進階一點還要評估是否存放的資料要去紀錄被編修的歷程並可設計資料修改的權限稽核機制等等。

Load這一層架構的良窳跟資料庫綱要的設計是否經過縝密的思考息息相關,資料表的資料是否必須具有唯一性(Uniqueness)、資料表格間相互參照的完整性(Referential Integrity)以及欄位資料是否必須強制性的有值或可接受的預設值等等。

最後我們小結一下,ETL如上所述,他是一個用來陳述這一整個複雜程序的名詞,而不是單指某項單一技術,有許多大型的軟體服務商針對ETL提供了所費不貲的專業服務,當然新創公司在發展時期無法負擔得起那些貴鬆鬆的服務時,也可以使用現在愈來愈流行的IaaS去建構自己的ETL資訊基礎建設,當然我真的還只是略懂而已,下一篇如果還講ETL的話,我會來分享我看過的一些案例,但因為我們公司將資料基礎建設完全投資在AWS上,所以我用的案例與實作都會以部署在AWS上為主,敬請指教。

 

Posted in AWS, Big Data | Tagged , , | Leave a comment

資料科學家?不是人呀!- 開疆拓土篇

4c847498b765ad804d5b885a72a8f39a

延續上一篇資料科學家?不是人!,身為一個資料科學家,究竟是加入新創公司好?還是加入一個已達快速成長規模的公司好?或換個方法說,是加入一個剛取得seed fund的新創公司好?還是加入一個剛取得一些traction的快速成長型新創好?還是乾脆直接加入像是Google、Facebook與Twitter這類規模已經極為龐大的網路公司好呢?

作者Robert Chang其實沒有給出一個明確的答案,當然我認為這也不會有標準答案的,但他有一段話說得非常好,那就是他認為,不論公司大小,一個資料科學家能夠從資料中萃取出價值的能力有很大的程度是奠基在他所屬公司在資料架構與平台上的成熟度

當資料科學家定義出研究目標,組織的資訊基礎設施能否對他們進行技術上的支援?例如該log的資料有無妥善是先定義好且log下來?該清理的資料有無自動化的data pipeline定期去清理?又或是散亂在各地的與不同資料源的資料有無完善的Data Lake進行儲存?這些資料基礎建設對資料科學研究不單是重要,而且也是相互強化的。

就像台灣軟體界這一兩年來非常熱衷於在組織內部導入DevOps,有時候一間網路公司有無良好的軟體開發流程甚至成為了該公司能否吸引優秀RD的重要指標之一,就像良好的開發流程與軟體工程師是互相強化一樣,好的資料基礎架構與資料科學家間也是相互扶持的。

再來就是,當公司處於不同的成長階段時,對資料科學的資源投放上也應該要有所輕重,對一個處於非常早期的新創公司(At early stage start-ups)來說,這時該著重的不應該是資料分析本身,而是去建立能夠支援往後階段的分析基礎建設,像是決定要logging哪些資料?是否早期就建立ETL程序以及去模型化資料並設計好資料綱要去追蹤並儲存公司營運過程中所產生的各種資料?

若新創公司營運正常並逐漸在市場上取得traction的時候(At mid-stage growing start-ups),這時不只公司在快速成長,公司內的資料累積速度應該也是處於加速狀態,這時要做的除了是因應資料累積加速的3Vs而去校正既有的Data Pipeline之外,還要開始有能力去從資料中產生出對公司商業營運上的洞見,像是定義出關鍵的成長KPI、找出組織成長的歸因,最重要的是透過資料產生的洞見去找尋公司下一個成長的機會之所在。

最後,當公司的商業模式獲得驗證,並在各方面進行大規模擴展的時候,這時對資料科學最主要的投資就會集中在如何從資料中去產生洞見來去建立並維繫公司在市場上的絕對競爭優勢,當然要強化的地方端看公司的《Domain Knowledge》在哪裡?以電商網站為例,是要透過資料分析後產生的洞見去強化網站上產品搜尋引擎的搜尋結果?還是要用來建構一個對使用者來說能產生更強大相關性的產品、內容推薦引擎?還是要透過資料分析來讓網站產品進銷存系統的運籌更具效率?在這個階段,因為data pipeline、data lake等資料基礎建設已經在前兩階段中循序漸進的發展完善,公司這時最需要投入的資源通常是找尋更多機器學習工程師、實驗設計者以及營運最佳化專家來好好的分析那些尚未創造出價值的raw data。

很多公司在導入資料驅動文化的初期,一定會經過一段艱困的磨合期,資料科學家們切記一定要與公司內的電腦科學專家們建立起良好的關係(當然反之亦然),因為當一家公司的創辦人之所以開始找尋資料科學家(你)加入,開始思考能否從自身擁有的資料中挖掘出能創造競爭優勢的洞見時,他們口中所謂的資料與可能的因果關係應該大都是來自於自己的腦補而已,當你進入公司之後,攤在你眼前最有可能的就只是一堆格式不齊、東缺西缺甚至是因果謬誤的Raw Data與log而已,這時該如何彌補這段Data Gaps(資料鴻溝)就得靠你與電腦科學家們的通力合作了,如何正確評估公司目前所處的營運階段、商業需求以及組織規模去決定該投入多少資源在適合的資料科學投資上,像是是否該先腳踏實地的把該logging與instrumention的地方下好程式去開始累積資料,還是該去商業開發能幫助公司既有資料集產生具啟發性洞見的第三方資料等等。

通常你的老闆(如果他是Andrew Ng,恭喜你!)是無法告訴你他倒底想要你從資料(他腦補中的)中分析出什麼的,所以你除了要跟工程師們好好的合作去取得你想要的資料集,你還必須要有良好的溝通與PR能力去讓你老闆知道你的價值,資料科學家必須要能夠以直白的方法去解釋公司內的資料給老闆聽,他們也必須找出新方法去定義對公司經營上有用的新指標,當然最重要的是要找出掩藏在龐大資料集中直觀看不出來的深度行為。

透過分析公司產品與資料去產生洞見是一個循環迭代的過程,資料科學家們必須不斷的去挑戰自己問出的問題,持續的關注公司商業模式的發展脈絡,並找出正確的資料集、定義出有效的features與label,如此往復持續下去,漸漸的資料驅動的文化就可以在公司內由被動的狀態往主動的方向移動,資料科學家就能開始主動的去建議實作公司創辦人或產品經理想都沒想過資料實驗,而這些資料甚至連他們都不知道存在於公司的資料基礎建設中。

祝好運!

Posted in Uncategorized | Tagged , | Leave a comment

資料科學家!不是人!

QIfIz9Vy

今天讀到一篇很棒的文章,作者是Twitter的資料科學家Robert Chang,讀完文章後只覺他文筆流暢且謙虛,因為仔細去Twitter與Google上查詢他的名字就可以發現他也是矽谷資料科學界的紅人,在Twitter、Quora與Linkerin上都可以看到他跟舊金山灣區許多大公司內的機器學習以及資料科學強者們頻繁的互動與討論,我當即就把他所有社群媒體上的profile都follow了。

這篇長文寫在他Twitter就職兩週年的那一天,文章內容主要是分享他在Twitter兩年間對資料科學如何應用在Twitter產品上摸索,以及懂得運用資料的人如何與工程團隊進行良好的互動讓透過資料科學產生的實驗成果去順利的產品化,更重要的是他提到,其實很多人都想知道如何成為一位夠格的資料科學家,關於這類的討論已經充斥於研討會以及網路的論壇上,但Robert認為大都太過於集中在討論技術、工具以及(也許)該有的技能樹等等,所以他覺得與其老生常談,倒不如透過記錄他在Twitter這兩年間與資料拼鬥並成功將實驗結果產品化的實戰經驗來讓有志於加入這領域的人們去更真實的理解到所謂資料科學家的價值何在。

Robert Chang說在Twitter這兩年間,機器學習已經滲透入Twitter的每一項產品之內,使用的工具也發生了大量的更迭,像是使用Scalding去替代Pig來管理Hadoop MapReduce去建構內部資料的pipeline,在組織上,資料科學家被嵌入在各個產品與工程團隊中去進行更緊密的協同合作,以他本身為例,他就被指派到Twitter的PIE(Product、Instrumentation and Experimentation)團隊去使用統計方法論來支援Twitter的A/B Testing團隊。

再來就是Robert也提到,真正的資料科學家這一個角色在矽谷(其實是整個地球上)依舊是一種如神話中獨角神獸般神聖的存在,因為他們要懂得實在是太多了,擁有從數學、統計學到計算機科學、機器學習、演算法再到資料視覺化這些偏技術上的技能還不夠,他們還需要擁有良好的寫作與溝通技巧,因為他們要能夠清晰的讓組織內外部的人理解透過他們研究所創造出的價值,更重要的是他們還必須有良好的專案管理能力,能夠將手上的任務進行優先權的制定並展現出堅定的執行力,最重要的是,他們也必須展現出強悍的領導能力去在組織中推動由資料驅動的產品開發文化。聽他講到這真覺得前途艱險呀!更讓人灰心的是,他說這種人在Twitter內居然還真的存在著(菸點)

聽到他講到這我就會想起一張很多人引用來說明什麼是資料科學家的一張文氏圖,如下圖所示:

os_signalcentral_what_is_data_science_gp_2014_v1.2_venn_diagram

資料科學由三個重要的領域緊密的扣起來,分別是電腦科學(Computer Science)、數學/統計學(Math/Statistics)以及領域知識(Domain Knowledge),三個領域交集處就是Robert Chang文章中所說的獨角聖獸。儘管如Robert Chang所說在Twitter中這種萬中無一的人才確實存在著,但要他們同時處理從資料科學研究到產品化中間所有的大小事是非常不切實際的,畢竟人一天就是那一丁點時間,為了能夠快速完成問題發現、資料蒐集、梳理、定義屬性、設定標籤到建立訓練模型到上線測試的迭代,透過團隊間的合作就成為必需的。

在文章中,Robert說他剛加入Twitter時其實經歷過一個找尋自身定位的煎熬期,因為如前所述,資料科學其實是一個龐大且複雜的跨學門的領域,初心者非常容易在其中迷失掉自我,隨著他自身經驗值的提升,他提出一個雖過分簡化但卻也很實務的二分法來去區分Twitter組織內部資料科學家的類型,分別是:

《Type A》資料科學家:A代表是Analysis,這類資料科學家非常擅長於解釋資料背後所代表的意義,他們擁有堅實的統計學學理基礎,但是他們只能用相對靜態的方式去處理資料,也就是說他們通常不具備有足夠的電腦科學能力去做資料清理(Data Clensing)、處理巨量的資料集與資料視覺化,他們通常也不見得有足夠的領域知識來去詮釋數據背後的意義,除此之外,他們通常無法透過良好的寫作技巧來與他人溝通數據所具有的價值。

《Type B》資料科學家:B代表Build,簡言之就是程式開發能力超強,受過良好的軟體工程訓練,他們或多或少也都有些統計學與數理知識,可以知道該用什麼樣的模型來去進行手邊資料的分析,也多少能理解模型輸出的數據所代表的意義,但這類資料科學家更熱衷的是將這些資料的研究成果去進行產品化,建立可以跟眾多使用者互動的網路服務,像是推薦引擎、精準廣告投放與更強大的搜尋引擎等等。

話說,看到Robert Chang提出這樣的二分法去試著定義他所認知的資料科學家時,不知為何心中想起當年《董卓》問《許臨》的一段話,《董卓》問:文人不能武,武者不擅文。文武俱備者稀,汝謂《呂布》是何人?

r4041

《許臨》:資料科學家(呂布),不是人呀!

Posted in Uncategorized | Tagged , | Leave a comment

阿猴讀論文:統計學與機器學習互補論?

maxresdefault

今天在Max Welling的profile上看到他寫的一篇文章,標題叫做Are ML and Statistics Complementary?,內文主要是Max Welling在第六屆IMSISBA中一個名為《Data Science in the next 50 years》的圓桌討論會上針對當代機器學習與統計學間的關係提出了一些他自己的想法,這篇文章引發很多人的討論,甚至連《FAIR》的深度學習大神Yann Lecunn也寫了篇臉書貼文來回應。

在Max的長文中他首先講到就機器學習跟統計學兩項學門來說,機器學習是一個相對年輕很多的學門,機器學習在發展的過程中吸取了很多有統計學而來的哲學以及方法論,例如在機器學習中,我們使用統計學中的最大概率(Maximum Likelihood)或貝氏理論(Bayesian)來做推估,我們也用最大期望值演算法(Expectation Maximization)來處理潛在變量(Latent Variables ),用無母數貝氏方法(Nonparametric Bayesian Methods )來做分類與分群。

儘管機器學習如上所說從統計學中吸取了許多養分,但他們兩者在文化上就有很大的差異,首先統計學專注在統計推論,從隨機抽樣中去解釋與測試母體的特性,而機器學習則更關注在執行預測,即使很多時候機器學習無法針對預測的結過做出良好的解釋。

Max接著提到我們正在經歷一個研究方法論的典範轉移,過去短短的幾年間,深度學習(Deep Learning)因為以下三個原因而被愈來愈多人所關注:

  1. 更強大的平行運算逐漸普及
  2. 愈來愈大量且多樣的資料開始被產生與搜集
  3. 建立模型所需要的參數愈來愈大量且難以被識別出與詮釋

Max說上述第一項與第二項因素是機器學習的第二天性,而第三項又奠基在前兩項,而且著重的是做出準確的預測而不是統計推論,而隨著深度學習的方法論基本上跟著以下的一個流程:

  1. 收集巨量的資料集
  2. 決定好要最小化的成本函數
  3. 設計一個類神經網路架構
  4. 套用一個隨機降階法(Stochastic Gradient Descend)去最小化成本

Max認為就長期來看,統計與機器學習這兩個學門將愈來愈難被拆分,我的理解是,因為機器學習著重在預測,要是做機器學習的人沒有足夠的統計學學理基礎的話,他就無法去詮釋模型產生的結果為何以及為何根據該結果所做出的決策是正確的,如果一個機器學習模型預測一個人有可能在未來患有阿滋海默氏症,醫生必須要能夠理解為何模型會做出這樣的判斷,而這判斷為真的機率又有多高,沒有諸如《Causal Reasoning》與《Calibrated Error-Bars》等統計學工具的輔助與詮釋的話,預測結果是很難讓人類理解與認同的,反之,統計學家雖然擅長於模型的詮釋,但他們即將要面對的學習問題將會愈來愈複雜,愈來愈大量的資料與更加複雜的演算法都需要更多的電腦科學知識才能應付得來,因此就長遠來看,兩個領域的合併是遲早的。

最後Max提出了幾個需要統計學與機器學習兩個領域緊密合作才能解決的資料科學問題,像是:

  • 如何做出公平的決策
  • 移除資料在搜集時所產生的偏誤
  • 在執行預測時同時保有資料的隱私性
  • 解開因果間的關聯
  • 建立良好的高維統計程序

以上等等

 

Posted in Uncategorized | Tagged | Leave a comment

來談談YouTube如何透過DNN去最佳化新一代的影片Thumbnailer(一):如何取出有用的Feature

youtube-space-in-tokyo

想信很多人都有在使用YouTube所提供的線上影音服務,他不僅免費,而且功能完整,而且經過某些認證程序後,使用者就可以上傳幾乎無限長度的影片(未認證前最長只能上傳十五分鐘長度的影片),因為使用者以及被上傳到YouTube的影片(以及相關meta data)已經非常的龐大,也因此在YouTube上逐漸衍伸出愈來愈多的商業模式,不論是商業品牌、素人明星乃至於當紅影歌星都會透過YouTube來當作營運品牌以及與粉絲、客戶們接觸甚至銷售的一個重要管道,在當今網路產業愈來愈倚靠廣告的現況下,YouTube也成為Google自家一個極為重要的廣告版位庫存。

供給與需求這樣一個幾近直觀的經濟法則掌管著一則影片在YouTube上被人們所看到的機會,過多的影片內容追逐著有限閱聽者那極度無耐心的關注度,沒有任何一則影片注定會爆紅,在過往我們可以看到有許許多多不被預期爆紅的YouTube影片為創作者帶來了可觀的經濟報酬,在商業領域中,我們也看到許多產生病毒傳播效應的YouTube影片對品牌形象與銷售營業額產生的推波效應,有許多人與文章都在討論究竟這些影片有沒有一個神秘的生產配方,有沒有一些相關的經驗可以學習,縱橫多篇相關研究論文我們可以稍微整理出許多可能性:影片標題、影片長度、影片中的人物、影片中有無明星與名人、影片中可愛動物出現的時間、影片的色彩組合、影片配樂、配樂編曲者乃至於廣告操作策略等等族繁不及備載,想要去預測一則影片發佈出去後的影響力,這是一項極度複雜且多項主觀與客觀因素混雜其中的任務,但有一個因素可能比上述各項被研究因素都還要重要的,那就是:影片略縮圖(Video Thumbnails)。

YouTube自行在研究Video Thumbnail時就有發現,對影片的創作者而言,視覺衝擊強烈、活潑生動且與影片內容高度相關的Video Thumbnail是可以誘發更多影片閱聽眾的點擊與觀看,甚至還會影響到他們在觀看影片時的專注力與觀看長度,YouTube在評估影片績效時有一個指標是用來觀察閱聽眾總共觀看了某則影片總長度中的多少百分比(備註:當品牌廠商拍攝的影片所要傳達的重要訊息座落於影片的50% ~ 75%間,這時閱聽眾是否有觀看到這段時間就顯得非常重要),反之對閱聽眾而言,相關度高的影片略縮圖是他們在找尋資訊時的一項重要指引,一圖抵千言千古明訓,與其在影片標題與說明上琢磨如何去吸引閱聽眾點擊,還真比不上一張誘人且充分傳達資訊的圖片。

如上所述,一則影片的略縮圖對影片的創作者與閱聽眾都是一個非常重要的指引,今天在Google的Research Blog上讀到一篇很有趣的文章,該篇文章主要是在討論Google如何透過深度學習來優化YouTube影片截圖挑選的功能,有使用YouTube的人都知道,當你影片上傳完成之後,YouTube都會顯示如下圖的一個略縮圖產生器(Thumbnailer),讓使用者去挑選最能代表這個影片的影片截圖去當作該影片在YouTube網站上的代表圖,在過去這種從影片中取出截圖的方法大都是採用固定時間去從整段影片中進行取樣,並在影片上傳完成後陳列在完成頁上讓使用者挑選,但是由於機器與演算法還無法透過讀完影片就能了解影片的前後文,因此挑選出來的圖片往往不見得能夠呈現出影片的製作者所想要陳述出的故事是什麼,也因為這樣,有設計能力與資源的個人或品牌就會自行去額外設計出一張能代表該則影片的素材,並上傳到YouTube去複寫掉那些透過演算法取樣出來但不適用的圖片。

YouTube-upload-video-thumbnail

因應這個問題,Google的影片內容分析團隊(Video Content Analysis Team)與YouTube創作者團隊(YouTube Creator Team)不久前開始攜手合作,他們透過找出許多可被Labeled的資料作為訓練資料集(Train Set),並實驗性的採用DNN(Deep Neural Networks)來優化自動被產生出來的影片代表圖(Thumbnail),就結果論來說,Google透過邀請大量真實用戶來捉對比較新舊方法所產出結果去進行了新演算法的成效評估,而這些受測者們認為透過DNN所產出來的Thumbnail有65%的效果是比舊方法所產出來得更好的,那YouTube究竟是如何達成的呢?以下就讓我們來看看!

在YouTube的系統架構中有一個名為Thumbnailer Pipeline的重要元件,當使用者把影片上傳到YouTube的時候,Pipeline會以一秒一個頁框的方式去對影片作取樣,然後送進一個名為Quality Model的演算法層,Quality Model會為每一個頁框的圖片指定一個Quality Score,然後分數最高的取樣圖會被選擇,並以他為基礎去產生要用在不同情境與裝置上多張大小與螢幕寬高比不同的圖片,可想而知,Quality Model是整個Pipeline中最重要的核心,也正是此次YouTube研發團隊用DNN(深度學習類神經網路)來強化的地方。

YouTube Thumbnail Quality Model

要針對一則影片透過演算法自動找出最佳的影片略縮圖是一項艱困的任務,影像識別技術雖然已經非常進步,但當涉及人類心智上的主觀判斷與個人偏好時,它(影像識別技術)能幫忙到的其實不多,視覺辨識可以輕易的在一則影片中辨識出是否有你喜歡的動物或是名人,但他還無法(也許是目前)透過分析影片的前後文更無法透過揣摩人類的主觀意見去自動化的為一則影片挑選出最適合的影片略縮圖。

為了解決這樣的問題,YouTube此次的跨團隊合作採用了機器學習(Machine Learning)中的監督式學習(Supervised Learning)方式,透過將一群下好標籤(Labeled)的訓練資料集搭配DNN去對Quality Model進行訓練,先撇除DNN在訓練過程中的作用,我們這邊先來看看研發人員如何對資料做標籤,在YouTube所有的影片Thumbnail中大致可分為兩種,第一種是透過演算法(演算法就是很黑箱,但是有興趣的小夥伴們可以看看Google所擁有這篇名為Context Sensitive Thumbnail Generation的專利)自動產生但是效果不算好的略縮圖,另一種就是由影片創作者精心設計過後透過YouTube所提供的上傳工具所上傳的客製化影片略縮圖(Custom Thumbnails),這類略縮圖通常格式精良,在設計或拍攝上也都能聚焦並至中在能夠表現出與影片內容最相關的主題上(例如音樂影片中的主角、歌手)。

High-Quality vs Low-Quality

左邊是使用者客製上傳的High-Quality的影片略縮圖,而右方是由舊演算法自動產生的略縮圖

YouTube新版的Thumbnailer將這些使用者客製後上傳的影片略縮圖標註為正面示範(Postive Examples也就是具有High-Quality),另一方面,將那些透過原本的演算法去自動產生出的影片略縮圖標註為負面示範(Negative Examples,也就是具有Low-Quality),透過這些High-Quality與Low-quality的Labeled資料集我們可以去建立起二元分類(Binary Classification)的訓練模型,YouTube的依舊在使用者上傳影片檔案時以每秒為單位將影片的頁框一張一張的讀取出來,只不過現在可以將這些頁框(Frames)一張一張的餵入二元分類模型中去做出傳入頁框的品質是屬於使用者客製影片略縮圖的品質還是透過舊演算法自動產生的低品質略縮圖。

下面這張圖是YouTube給出的一個範例,圖片上方標註為Low Quality的那一排影片略縮圖是透過舊演算法去將影片的頁框一秒一秒的擷取出來,而下面標註為High-Quality的則是透過DNN改良後的Thumbnailer去擷取出來的,兩相比較後可以清楚的看到不論是在取景的重點選擇上還是在影片主題的聚焦與位置挑選上,透過DNN訓練出來的Quality Model所挑出的影片略縮圖都明顯的優於沒有使用DNN的舊演算法。

image03

第一排標註為Low Quality的略縮圖是尚未採用DNN前的舊式演算法,而第二排標註為High Quality的略縮圖則是透過DNN所訓練出來的演算法所挑選出來的

下面這張圖也是YouTube給出的新舊影片略縮圖挑選演算法所選擇出來圖片間的品質差異的展示範例:

image01在本篇文章中,我簡單地為各位小夥伴們介紹了YouTube是如何透過DNN加上從既有的大量資料中去萃取出具有學習潛力的特性(Features)來當作學習模型中的訓練資料集(Training Set),在更進一步深入DNN之前,我想先聊聊我在YouTube這過程中學到什麼?其實我感受最深的不是技術層面,像是什麼Machine Learning以及深度類神經網路還是Quality Model等等,我看到的是一個持續精益求精的技術團隊以及一個容許實驗精神的公司文化,在對的時間找到適當的方法去讓自身產品循序漸進的去滿足使用者,沒有深度學習演算法與硬體運算能力在這些年長足的進步,沒有可Training資料的累積,今天YouTube這樣的改良工程都是不可能發生的,理性的思考所有的限制,然後在產品開發上訂出優先順序,而非本末倒置去追求最高新的技術然後去滿足使用者沒那樣痛的問題,著實是制定產品發展策略的人們該從中學習的。

Posted in Uncategorized | Leave a comment

PHP相依性管理工具Composer – 基本套件版本號設定方式

izler-revenge-composer-orchestra

近期公司在產品開發上處於一種越級打怪的狀態,連續好幾年在不大不小的專案中打滾,很多新東西都沒有跟上去(也可以說是舒適圈待久了),很多該設計與執行的開發流程也都很鬆散,導致公司在產品開發上一直都沒有建立起一個讓團隊成員們去進行良好協同運作的環境。

再來就是除了開發流程之外,也覺得對於PHP技能的掌握一直都停留在好幾年前,所以痛定思痛的靜下心來開始了這一系列的返樸歸真系列文章,內容除了是些日常學習的筆記之外,另一個目的也是順道整理要在公司內部進行分享的一些內容,今天就讓我們開始來討論一個近年PHP才開始引入的相依性管理工具:Composer

Composer有許多的啟發來自於Node.js的npm以及Ruby的Bundler,但是Composer官方文件在中並不將自身定義為套件管理工具,而是各個獨立專案中的套件相依性管理工具,預設上透過Composer安裝的套件會存放於專案下一個名為vendor的資料夾中,而不是作業系統全域的範圍。

說明確一點,Composer解決以下幾個問題

  1. 當你有個專案相依在一個或多個第三方的PHP專案上(例如monolog是很常用來做file log的一個第三方PHP專案)
  2. 當你專案所相依的第三方專案又相依於其他第三方專案上的時候(例如Facebook的PHP SDK就相依在guzzle這一個專案上)
  3. 當你透過composer.json宣告你的專案相依於其他的套件上時
  4. Composer會自動去找尋那你的專案相依於哪些專案上以個各自最適的專案版本號是哪些,並自動安裝(根據composer.json裡的設定)

以下以一個我正在開發的廣告產品為例,在專案下有一個composer.json,裡面內容是:

透過上面的範例大家可以看到Composer的套件名稱由兩個部分組成,分別是套件開發者的名字以及反斜線後的套件名稱,以Facebook的PHP SDK為例,他在composer.json是透過”facebook/php-ads-sdk”去定義,其中facebook就是開發者的名稱,而反斜線後的”php-ads-sdk”就是套件的專案名稱。

知道套件的命名方式之後,接下來就是比較複雜的地方了,那就是安裝套件版本號的指定,在composer.json中你可以透過指定明確的版本號,或是使用版本號範圍甚至加上萬用字元等等方式來去安裝套件,以下讓我以monolog這個package來一個一個來實際測試給各位看看

範例一:指定明確的版本號

執行安裝的結果如下圖所示

螢幕快照 2015-04-21 下午8.49.31

大家可以看到composer依照我寫在composer.json中的設定,明確地幫我把版本號為1.12.0的monolog安裝在專案下一個名為vendor的資料夾中,儘管目前他在github上的版本號已經到達1.13.1

螢幕快照 2015-04-21 下午8.52.17

範例二:指定要安裝套件版本號的範圍

在composer.json中,你可以使用大於(>)、大於等於(>=)、小於(<)、小於等於(<=)來設定你所要安裝套件的版本號,除此之外,你還可以透過逗號(,)與空白來代表AND或是使用”||”來代表OR去建立複合條件,假如我們將上一個例子中的composer.json改為

執行完composer install之後,我們可以看到如下圖的安裝結果

螢幕快照 2015-04-21 下午9.05.15

composer在我要求版本號至少要大於1.10.0但沒有設定最高版本號的安裝條件下,他自動地去抓了最新版本(1.13.1)的monolog並安裝到vendor資料夾裡面,其實很多時候這不見得是一件好事,因為很有可能你一個不小心就升級到一個不具有向後相容性的套件版本,然後你的專案就爆了,所以在比較安全的實務下,最好設定一個你所知道安全的版本號範圍,例如把composer.json改成如下

執行安裝後結果如下

螢幕快照 2015-04-21 下午9.17.05

大家可以看到,因為我設定的套件版本號條件為必須大於”1.10.0″但是要小於等於”1.12.0″,所以他會去抓取monolog套件現存版本中滿足我所設定版本號條件的版本下載並安裝到vendor中,以monolog來說,他會下載monolog 1.12.0。

範例三:透過連字符號(Hyphen Range)來設定要安裝的套件版本號

除了透過上例中的範圍符號來設定要安裝的套件版本號之外,composer也接受使用連字符號來達到一樣的效果,我們再將composer.json改為如下

大家可以發現他的安裝執行結果就跟前一個使用範圍符號(Range Operator)的composer.json一樣,composer會去安裝符合條件中最高的那一個版本號來安裝套件,如下圖所示:

螢幕快照 2015-04-21 下午9.33.20

composer會去下載版本號為”1.12.0″的monolog到安裝目錄vendor之中。

範例四:透過通配符號(Wildcard)來設定安裝版本號

通配符號(Wildcard)或是所謂的萬用字元也可以用在composer.json的設定中來告訴composer要去安裝哪一個版本號的套件,如上例,他其實等同於

也就是說composer會去找尋目前monolog套件所有版本號中大於或等於1.13.0但小於1.14版本的monolog去下載並安裝入vendor中,執行結果如下圖所示:

螢幕快照 2015-04-21 下午9.47.26

範例五:Tilde Operator

以上的composer.json的範例中,我們使用了Tilde Operator(~)來告訴composer我們要安裝的AWS PHP SDK套件的版本號,”~2.8″等同於告訴composer我要安裝版本號必須要滿足”>= 2.8″同時要”<3.0.0″的條件。

執行完composer install之後,我們可以看到如下圖的結果

螢幕快照 2015-05-01 下午2.40.38

composer幫我安裝了版本號為”2.8.2″的AWS PHP SDK,我們去AWS PHP SDK在github上的專案頁去查看一下

001

我們可以看到目前該專案版本號最高為”2.0.0-beta.1″,而以”2.8″開頭的各專案版本中以”2.8.2″為最高的版本號,所以composer會挑選版本號”2.8.2″作為要安裝到我專案中的AWS PHP SDK。

範例六:Caret Operator(^)

此範例中我們改為使用Caret Operator來告訴composer要安裝的AWS PHP SDK版本,在composer.json中設定版本號為”^2.8.0″等同於告訴composer說:請幫我下載”aws/aws-sdk-php”,而版本號必須同時滿足”>=2.8.0″以及”<3.0″,以下就讓我們執行”composer install”看看結果為何?

螢幕快照 2015-05-01 下午4.13.28

各位可以看到執行結果是composer透過composer.json中索設定的”^2.8.0″幫我去package的repository中下載了版本號為”2.8.2″的”aws/aws-sdk-php“進我的vendor資料夾中。

讓我們不厭其煩的來確認一下這樣的結果是否符合我們的預期?

001

上圖是AWS PHP SDK位於Github上的Repository的截圖,目前最高版本號是”3.0.0-beta.1″,而composer.json中”^2.8.0″的設定告訴了composer在下載package進入vendor之前package的版本號必需滿足”>=2.8.0″且”<3.0″的複合條件,因此,composer幫我們下載了”2.8.2″進入vendor資料夾中是符合我們設定要產生的行為。

透過以上的說明,相信同學們都瞭解了composer.json中套件版本號的所有設定規則,在下一篇文章中,我將會跟各位同學解釋一個很重要概念,那就是”Semantic Versioning(語意化版本號)“,敬請期待。

Posted in Uncategorized | Leave a comment

返樸歸真重新認識PHP – Namespace Keyword與Constant?

旋窩鳴人 vs 黑暗旋窩鳴人(self)

經歷過前面三篇針對PHP 5.3+新功能介紹的文章之後,相信大家對如何去組織PHP網路應用的方式已經有了全新的認知,不過眾多(筆者腦補ing)讀者們已經迫不及待想要咱家我來介紹PHP7裏面的高大上玩意了,不過沒關係,萬丈高樓平地起,咱們還是一步一步來吧!今天的文章咱們要來討論PHP 5.3+引入的Namespace機制下的一些有用的小功能:Namespace KeywordNamespace Constant

假設我們有一支程式內容如下:

當我們要在程式中使用定義在上述程式命名空間”Urad\Thirdparty\DoubleClick\OpenBidder”裡的類別時,在別名(Aliases)與”Fully-Qualified Name”之外,我們還可以透過全域常數”__NAMESPACE__”以及命名空間關鍵字”namespace”來達成,以下就讓我們來用程式demo一下,不過在demo前先讓我來說明一下demo程式碼在我DSP產品上的使用情境。

如果小夥伴們還有印象的話,在上一篇文章中我有簡單的解釋到Google DoubleClick的OpenBidder有三種廣告競價模式:OpenRTB、Native以及Hybrid,所以我程式在組織上會有三個主要的PHP Class個別以OpenRTB、Native還有Hybrid為命名,並將他們都定義在命名空間”Urad\Thirdparty\DoubleClick\OpenBidder”裏面,在之後的程式中我就可以透過如下的方法去Import進來取用,如下所示

上述程式碼中的的OpenRTB、Native與Hybrid都是用來定義廣告競價”模式”的類別,但是我真正要做的是完成廣告競價這件事,所以我會另外在命名空間”Urad\API\RESTful”中定義一個名為”RTB”的類別(Class),我要用它來完成接下來要進行的廣告競價,如下所示:

RTB類別主要的功能是執行Google DoubleClick的廣告競價,但要採用Google OpenBidder的何種競價模式要靠透過建構子傳入競價模式的物件(透過OpenRTB、Native或是Hybrid來初始化),在上面RTB類別的程式碼中我簡化到只留下方法”getRtbBidMode()”輸出目前競價採用的競價模式,並透過此方法來回傳目前使用的競價模式名稱。

執行上述程式碼,預期輸出結果將會如下所示

相信透過上面平鋪直敘的說明(?),大家對”__NAMESPACE__”一定已經有了一定的認識,接下來我們介紹另一個非常相似的功能,那就是關鍵字namespace。關鍵字namespace用起來有點像是Class中的self關鍵字,它用來在關聯到目前程式所屬的命名空間自己,說起來有些抽象,讓我們直接看看下面的範例:

大家可以看到上面的程式碼只是改成用關鍵字”namespace”直接去關聯到自身所代表的命名空間”Urad\API\RESTful”中的類別RTB,然後用”new”關鍵字把該類別初始化成一個新的物件,相當簡單,輸出結果將如同前一段使用”__NAMESPACE__”的程式碼一樣

很簡單吧!好的!在如此平鋪直敘的說明完”__NAMESPACE__”與”namespace”之後,我們終於要在下一篇文章中進入Auto Loading了,敬請待續囉 ~ ~ ~

Posted in Uncategorized | Leave a comment

返樸歸真重新認識PHP – Aliases(別名)

EONFX-206

延續前兩篇分別討論NamespaceImport的文章,我們今天將會開始對PHP 5.3以後所引入的別名(Aliases)機制進行討論。其實別名機制非常好理解,簡單說就是它讓開發者在程式中可以用簡短的名稱去替代引入的長命名空間。因為命名空間的出現就是要讓開發者去避免在撰寫自幹函式庫或是引入第三方函式庫時在類別與方法、常數、變數上發生命名的衝突,所以在一般狀況下,它的名稱都會非常的落落長,以我自己的函式庫為例會有如下的命名空間:

以下我們以我所撰寫的Google DoubleClick函式庫為範例,由於Google DoubleClick在進行廣告版位的競價時有以下三種模式可使用:OpenRTB、Native以及Hybrid,所以在命名空間”Urad\Thirdparty\DoubleClick\OpenBidder”以下我用三種模式各自的名稱建立起了三個Class,如下所示

OpenRTB.php

Native.php

Hybrid.php

假如我現在要取用上述寫好的Google DoubleClick函式庫,在使用別名前,我都要這樣寫:

上面那段程式碼在螢幕上的輸出結果預期將會是

但在我採用PHP 5.3+所提供的別名(Aliases)機制後,我就可以將程式改寫成如下更簡潔的形式

執行上述使用了別名機制的程式之後,預期輸出結果將會如下

各位小夥伴應該發現,Aliases(別名)其實是一個很簡單的工具,但是透過它卻可以提升在撰寫PHP物件導向程式時很大的便利性與彈性, 在開發大型PHP應用時可以好好的善加利用,在下一篇文章,我們將會繼續進入keyword以及Auto Loading這一個非常重要的PHP開發機制,敬請繼續關注 :)

葉佩雯專區:urAd 2015年第一季廣告技術研發戰力擴編中

 

Posted in Uncategorized | Leave a comment