2018年10月27日 星期六

[研究] 關於 Bayesian Global Optimization



目前我們使用的是Python 版的 gpyopt
另外有商業版的:SigOpt 
介紹關於Bayesian Global Optimization:
一般常用的兩種方法是,但是都很吃資源:     
  • Grid search     
  • Random search
關於Spark 有支援的lib:

其它關於SigOpt 討論 Bayesian Global Optimization


目前市面上有的選擇:Optimizing hyperparams with hyperopt

介紹 Bayesian Global Optimization 的投影片

關於 Bayesian Optimization 的應用









2018年9月24日 星期一

加速 (Accelerate) - 測量的誤區以及你該測量什麼

soruce: measurement



從二十世紀初開始,科學管理之父泰勒(Fredrick W. Taylor, 1856-1915) 就開始推廣的科學化管理,也就是運用科學方法(觀察、測量、實驗、分析、比較)來解決管理問題,這個立意可能是好的但是也最容易被誤用,所以加速 (Accelerate) 這本書第二章開頭先不說該測量什麼,而是不該怎麼量。

還記得大學時候的軟體工程聽到的測量指標 line of Code 就是一大誤區!!

2018年9月20日 星期四

加速 (Accelerate) - 關於成熟度模型與能力模型的差異

圖片來源: Accelerate


加速 (Accelerate)是 2018 年  martinfowler 最推的一本書

第一章的重點在介紹與傳統成熟度模型(maturity model)相比,能力模型(capabilities model)看重的是什麼,主要的差異有四點:

  1. 成熟Model 目標是幫助組織達到成熟這個目標,換言之代表停止成長,而能力是可以不斷改進進步的
  2. 成熟模型是線性的,一個階段一個階段的前進升級,但是成長模型卻是多維度的和動態調整的,所以可以根據組織現況去調整,而不像成熟度模型一體適用的。(以現階段來說公司重點可能是著重在發展某個能力,而不是一個等級幾的絕對指標)
  3. 能力模型專注在"成果",以及怎麼藉由改善影響成果,所以可以根据讓領導者和團隊成員根據自身狀況調整目標,不像成熟度模型是測量技術等級和工具使用狀況等指標
  4. 最重要的就是成熟度模型給組織的目標只有靜態的等級和流程,但是卻忽略了,商業和技術卻是一直在變化的,很多在過去是高績效的指標到了現在可能反而低效的指標。

而下一章則是開始介紹本書認為重要的24項能力指標。

謎之音:根本就是對 CMMI 打臉,打好打滿~



2018年7月4日 星期三

做自己的生命設計師 - 如何敏捷過好你的人生



問自己問題


做自己的生命設計師中提到,我們每個人都很容易陷入一個叫做"重力問題"的陷阱裡。
所謂的重力問題就是說,有些問題就像地球的重力一樣,你是沒辦法解決的。在規劃人生的時候,如果某些問題解決不了,那它就不是真正的問題,而隻是一種情況,一種環境,或者一種生活現實。面對這種重力問題,唯一的解決途徑就是接受它。

生命設計師不是讓你找到希望到達的地方,更不是你認為自己應該在的地方,而是讓你瞭解當下所處的真實位置。

2018年6月16日 星期六

[Spark 學習小筆記] 什麼是 Hyperparameter Tunning? 有什麼方法?



不論在學習或是工作常常都經歷過一段知其然不知其所以然的階段,是否能突破其實就是看有沒有這個機運和決心去突破,話說之前在翻譯 Spark ML 那本書時,看到 Grid Search (網格搜尋) 和 Random Search (隨機搜尋) 的時候其實是一頭霧水,只知道是用來搜尋Hyperparameter 的演算法,但是原理和如何使用卻是一無所知,直到最近開始利用Spark 開發Machine Learning 專案,就慢慢開始有感覺了。

2018年6月1日 星期五

關於 2019 年 Oracle Java 即將收費有什麼是我們必須知道的?


最近網路上吵的沸沸揚揚的話題之一就是Oracle Java 將要對商業用途收費,相關的新聞也不少:

然後這些話題在ptt 和Facebook TWJUG 也引起很大的討論

資料來源:Facebook TWJUG


但詳情究竟是怎樣呢?其實我觀察到應該是兩個議題被混再一起討論,造成的恐慌:
  • 一個是已經存在已久的商業授權議題
  • 另一個是Oracle java 8 在 2019年更新要收費

Java 商業授權的定義


首先官網開宗明義就回答Java 是否還是免費?

Is Java still free?

The current version of Java - Java SE 9 as well as Java SE 8 - is free and available for redistribution for general purpose computing. Java SE continues to be available under the Oracle Binary Code License (BCL) free of charge. JRE use for embedded devices or use of commercial features may require a license fee from Oracle. Read more about embedded use of Java SE or contact your local Oracle sales representative to obtain a license.

請參考官網:
另外有興趣的可以參考這份報告:


根據這份報告的結論,會被收費的應該是:
  • 使用 Commercial feature 功能的公司
  • Non-General Purpose Computing Usage
  • Embedded use of Java SE (這應該就是針對POS/ 網通...等設備廠商)
所以一般提供雲端/網站服務的公司是應該不算在收費範圍,唯一弔詭的用詞在這段:

Any usage of the Java SE8 software programs that does not fall under the “General Purpose Computing Usage”, is by definition “Non-General Purpose Computing Usage” and as such required to be licensed separately through Oracle Corporation.

那到底什麼是一般用途使用?XDDD


關於Java 8 升級收費


根據官網資料:

Public updates for Oracle Java SE 8 released after January 2019 will not be available for business, commercial or production use without a commercial license.



我的解讀就是,Java 8 我們不想再維護摟,所以大家趕快升級去用新版的Java 9 甚至10唷,但是有些比較有錢的公司必須繼續使用Java 8 的話,那要我們幫忙升級patch 那就繳錢吧....:P




2018年5月21日 星期一

阿里鐵軍 - 企業價值的考核



阿里鐵軍第二章講的是公司的願景,教育訓練和績效考核,先來看看阿里巴巴的價值觀的演進,從原本的獨孤九劍:
  • 創新
  • 激情
  • 開放
  • 教學相長
  • 群策群力
  • 質量
  • 專注
  • 服務與尊重
  • 簡易

精簡為六脈神劍:
  • 客戶第一
  • 團隊合作
  • 擁抱變化
  • 誠信
  • 激情
  • 敬業

乍看一下跟一般公司的價值觀沒什麼差別,不過就是口號罷了?大部分的公司可能把價值觀當口號喊完就算了,了不起讓員工能都能背起來,但是如果要落實價值觀呢?阿里的觀念就是把它融入到考評系統,在阿里巴巴價值觀考核和業績考核各佔50%,但是最讓我感到好奇的就是對於價值觀的考核??考評員工是否有符合這些價值觀?到底該怎麼做呢?作文大賽嗎?XD

很好奇的上網查了一下,每條價值觀都有具體的行為準則和等級,然後如果符合也必須舉出具體案例(不管是自評和長官評),雖說上有政策下有對策,KPI 訂出來都可能被玩弄,但是對於大部分的人來說都是很具體可以落實的,不是那種虛無縹緲自己覺得給自己幾分,或是長官覺得給你幾分就幾分


而對於用人的準則也有整理如下(真得很愛取名字和口號XD)




另外也找到下面這個投影片做的蠻不錯的。






2018年5月10日 星期四

Spark 小技巧系列 - 讀取檔案過大發生 java.lang.NegativeArraySizeException 該怎麼處理?


雖然我們知道單一檔案不要太大,或太小,但是有時候人在江湖身不由己,如果遇到單一檔案太大時,系統可能就會噴出以下錯誤:


[WARN] BlockManager   : Putting block rdd_12_0 failed due to exception java.lang.NegativeArraySizeException.
[WARN] BlockManager   : Block rdd_12_0 could not be removed as it was not found on disk or in memory
[ERROR] Executor          : Exception in task 0.0 in stage 3.0 (TID 259)
java.lang.NegativeArraySizeException
        at org.apache.spark.unsafe.types.UTF8String.concatWs(UTF8String.java:901)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificUnsafeProjection.apply(Unknown Source)
        at org.apache.spark.sql.execution.aggregate.AggregationIterator$$anonfun$generateResultProjection$1.apply(AggregationIterator.scala:234)
        at org.apache.spark.sql.execution.aggregate.AggregationIterator$$anonfun$generateResultProjection$1.apply(AggregationIterator.scala:223)
        at org.apache.spark.sql.execution.aggregate.ObjectAggregationIterator.next(ObjectAggregationIterator.scala:86)
        at org.apache.spark.sql.execution.aggregate.ObjectAggregationIterator.next(ObjectAggregationIterator.scala:33)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage3.processNext(Unknown Source)
        at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
        at org.apache.spark.sql.execution.columnar.InMemoryRelation$$anonfun$1$$anon$1.hasNext(InMemoryRelation.scala:139)
        at org.apache.spark.storage.memory.MemoryStore.putIteratorAsBytes(MemoryStore.scala:378)
        at org.apache.spark.storage.BlockManager$$anonfun$doPutIterator$1.apply(BlockManager.scala:1109)
        at org.apache.spark.storage.BlockManager$$anonfun$doPutIterator$1.apply(BlockManager.scala:1083)
        at org.apache.spark.storage.BlockManager.doPut(BlockManager.scala:1018)
        at org.apache.spark.storage.BlockManager.doPutIterator(BlockManager.scala:1083)
        at org.apache.spark.storage.BlockManager.getOrElseUpdate(BlockManager.scala:809)
        at org.apache.spark.rdd.RDD.getOrCompute(RDD.scala:335)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:286)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
        at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96)
        at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53)
        at org.apache.spark.scheduler.Task.run(Task.scala:109)
        at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748) 

2018年5月9日 星期三

Spark 小技巧系列 - left join 後把null 改為0


如果使用Spark 的 left outer join 遇到沒有的資料通常就會以NULL顯示,如下圖所示:


這時候如果我想要計算CTR = click/ impression 會發生什麼事?直接噴錯給你看,然後也不知道發生什麼事....

org.apache.spark.sql.AnalysisException: Resolved attribute(s) 'impressionCount,'clickCount missing from viewCount#965L,(impressionCount / total)#582,dsType#1189,rid#14,impressionCount#534L,recommendCount#1198L,clickCount#1441L,siteId#16 in operator 'Project [siteId#16, rid#14, impressionCount#534L, (impressionCount / total)#582, viewCount#965L, dsType#1189, recommendCount#1198L, clickCount#1441L, ('clickCount / 'impressionCount) AS CTR#2022]. Attribute(s) with the same name appear in the operation: impressionCount,clickCount. Please check if the right attribute(s) are used.;;
'Project [siteId#16, rid#14, impressionCount#534L, (impressionCount / total)#582, viewCount#965L, dsType#1189, recommendCount#1198L, clickCount#1441L, ('clickCount / 'impressionCount) AS CTR#2022]
+- AnalysisBarrier
      +- LogicalRDD [siteId#16, rid#14, impressionCount#534L, (impressionCount / total)#582, viewCount#965L, dsType#1189, recommendCount#1198L, clickCount#1441L], false


    at org.apache.spark.sql.catalyst.analysis.CheckAnalysis$class.failAnalysis(CheckAnalysis.scala:41)
    at org.apache.spark.sql.catalyst.analysis.Analyzer.failAnalysis(Analyzer.scala:91)
    at org.apache.spark.sql.catalyst.analysis.CheckAnalysis$$anonfun$checkAnalysis$1.apply(CheckAnalysis.scala:289)
    at org.apache.spark.sql.catalyst.analysis.CheckAnalysis$$anonfun$checkAnalysis$1.apply(CheckAnalysis.scala:80)
    at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:127)
    at org.apache.spark.sql.catalyst.analysis.CheckAnalysis$class.checkAnalysis(CheckAnalysis.scala:80)
    at org.apache.spark.sql.catalyst.analysis.Analyzer.checkAnalysis(Analyzer.scala:91)
    at org.apache.spark.sql.catalyst.analysis.Analyzer.executeAndCheck(Analyzer.scala:104)
    at org.apache.spark.sql.execution.QueryExecution.analyzed$lzycompute(QueryExecution.scala:57)
    at org.apache.spark.sql.execution.QueryExecution.analyzed(QueryExecution.scala:55)
    at org.apache.spark.sql.execution.QueryExecution.assertAnalyzed(QueryExecution.scala:47)
    at org.apache.spark.sql.Dataset$.ofRows(Dataset.scala:74)
    at org.apache.spark.sql.Dataset.org$apache$spark$sql$Dataset$$withPlan(Dataset.scala:3295)
    at org.apache.spark.sql.Dataset.select(Dataset.scala:1307)
    at org.apache.spark.sql.Dataset.withColumns(Dataset.scala:2192)
    at org.apache.spark.sql.Dataset.withColumn(Dataset.scala:2159)


其實原因就是有Null的存在,這時候只要使用以下技巧補零就可以了。

Dataset join1 = impression.join(broadcast(view), col, LeftOuter.toString())
                               .na()
                               .fill(0, new String[] {"viewCount"});

這段的意思就是會把null 的值,補上任何你想要的值,然後就解決了~


2018年5月3日 星期四

加速 Spark 寫到雲端儲存空間(AWS S3/ Azure blob/ Google GCS )的速度



不知道大家有沒有遇到過明明 Spark 程式都結束了,檔案也寫完了,Driver program 確還不會停止,感覺就當在那邊的經驗?

很多技術細節沒有遇到還真得不知道會有這種設計和改善的方法,會發現這個密技是因為下面幾個條件同時成立才注意到的:

1. 使用雲端儲存空間


為了節省成本,我們並沒有架設自己的HDFS Server,取而代之的都是把要分析的資料和結果儲存在雲端儲存空間( AWS S3/ Azure blob/ Google GCS)。這個選擇會大大降低維運成本和提高檔案的保存可靠度,不過缺點就是失去data locality 的速度優勢,而且每次分析都從雲端拉檔案下來也會花不少時間,所以就是以時間效能換取成本和可靠度。

2018年4月27日 星期五

[Spark 學習小筆記] 如何使用Java 實作 vectorization (1)


Vectorization 的重要性


還記得上Anfrew Ng 的deep-learning課程前幾堂課就講到vectorization的重要性,以及對於效能會有怎樣的影響,對於矩陣運算,最直覺的反應就是寫個for loop,然後針對每個emlement 去做運算,但是其實CPU&GPU 有專門的指令集可以用來平行化專門處理這種運算,於是透過 vectorization 就可以得到顯著的效能改善,下圖就是老師上課時用python 的範例,相差了400多倍!?

2018年4月24日 星期二

Apache Spark 學習三部曲:學會他,除錯他,寫好他



最近密集的在寫Spark 程式,感覺到終於該開始往下個階段邁進了,其實就像學習任何程式語言和Framework,Spark 學習也分三個步驟:
  1. 如何寫
  2. 如何調教/錯誤排除
  3. 如何寫的好

學會如何寫,網路上有不少的範例,不過大多是Scala和Python,如果要翻成Java版還需要額外花點功夫,等到開始寫一些程式丟到spark 上面跑,又會開始遇到一堆奇奇怪怪的錯誤訊息,比如說:
  • Futures timed out after [300 seconds]
  • This timeout is controlled by spark.executor.heartbeatInterval
  • cannot assign instance of java.lang.invoke.SerializedLambda to field org.apache.spark.sql.UDFRegistration$$anonfun$27.f
  • Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient memory


這時候就要開始學習怎麼調教系統參數和錯誤排除,下面這個網站整理的蠻不錯的,把Spark performance tuning 分成幾大塊,分別是:
  • Data Serialization
  • Memory Tuning
  • Memory Managemnt
  • Data Structure Tuning
  • Garbage Collection Tuning




最後就是程式都會動了,但是怎麼要跑那麼久?這時候就應該開始瞭解Spark 許多底層的運作原理,要怎麼寫才是正確的,怎樣寫才會有比較好的效能,下面收一些在學習spark 時收集到的不錯資訊:



其它網路文章:


最後要提醒自己:

先求有,再求好,等到程式會動了,確定結果是大家想要的,有符合商業價值了,再來調教也不遲!

2018年4月17日 星期二

[筆記] 要如使用Unicode Range 濾掉文章的特殊字元


最近在實作文章(中文)抽詞,斷詞的程式,其中要做的一件事就是把一些符號和標點符號濾掉,在網路上google 都會搜尋到五花八門的範例,常見的regular expression如下:
  • !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
  • ['?:!.,;]*([a-z]+)['?:!.,;]*

如果沒有好好去瞭解,其實都會被這些眼花繚亂的符號所迷惑,其實很多多東西在Java的文件裡面都有定義好了,只是從來都沒有好好去研究 (遮臉)。參考Java Pattern的文件其實很輕易的就可以列舉出所有的符號:

POSIX character classes (US-ASCII only)
\p{Lower} A lower-case alphabetic character: [a-z]
\p{Upper} An upper-case alphabetic character:[A-Z]
\p{ASCII} All ASCII:[\x00-\x7F]
\p{Alpha} An alphabetic character:[\p{Lower}\p{Upper}]
\p{Digit} A decimal digit: [0-9]
\p{Alnum} An alphanumeric character:[\p{Alpha}\p{Digit}]
\p{Punct} Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph} A visible character: [\p{Alnum}\p{Punct}]
\p{Print} A printable character: [\p{Graph}\x20]
\p{Blank} A space or a tab: [ \t]
\p{Cntrl} A control character: [\x00-\x1F\x7F]
\p{XDigit} A hexadecimal digit: [0-9a-fA-F]
\p{Space} A whitespace character: [ \t\n\x0B\f\r]


但是真實世界往往不只這樣,除了一般ASCII符號外,其實現在越來越多怪異的 Unicode 符號也會出現在文章中,比如說:
  • "─" U+2500 Box Drawings Light Horizontal Unicode Character
  • "⋯" U+22EF Midline Horizontal Ellipsis Unicode Character - Compart
  • "䶵" U+4DB5  cjk Ideograph Extension A, Last
甚至最近連emoji 也非常常出現:
到底emoji 需不需要濾掉呢?這個問題我也不知道,不過至少確定許多符號都應該要濾掉,為了方便使用就把要濾掉的特殊字元整理如下:



有興趣的歡迎取用~

2018年3月20日 星期二

[情報] 目前市面上有哪些 Open Source Function As Service (FaaS)



前陣子因為好奇加入了 Cloud Native 的Slack 群組,看看最近熱門在討論的話題是什麼,有什麼有趣的技術正在發展,最近就剛好看到一個有趣的投票話題,請大家推薦 open source 的 FAAS Solution。



2018年3月17日 星期六

非技術團隊的敏捷與自省會議


究竟非技術團隊也適合跑敏捷方法嗎?一直以來我對這個議題也蠻感興趣的,如果適合那該怎麼推行和實踐呢?雖然以前有上網找到了一些文章,不過沒有實際執行過也不會有感覺。

其實敏捷推行久了慢慢會發現,其實瓶頸可能已經不在技術團隊,而會轉移到其它非技術團隊,或者應該說瓶頸往往產生再技術團隊與非技術團隊的交付以及溝通的過程,而一間公司和一個集團想要能更加的成長茁壯,就必須不分團隊別的共同進步與成長,這也是Lean 與 DevOps 的精神。

2018年3月13日 星期二

透過Java開發 Spark 2.x ML 的 LDA (Latent Dirichlet allocation) model 的感想

借用 Deep Learning 那門課的一張投影片來代表我最近在做的事,一直不斷的在轉圈圈,但是其實更多時候腦袋都是下圖這種轉圈圈:


主要的挑戰如下:
  1. 第一次用Spark 寫 ML 相關的程式,然後網路上的範例和討論幾乎都是用 scala 和python 寫的,為了要轉成Java版花了不少力氣。
  2. 資料散亂且難以理解,關於LDA 的文章幾乎都是論文等級了,充滿了難以下嚥的數學公式,往往都是直接略過,而且關於LDA 和 Spark ML 相關的中文討論又是以大陸居多,不過也因此挖到不少寶。

Spark ML 內建的Pipeline 主要分為以下四個步驟:



不過後來才發現Spark ML 的 pipeline 是給 supervisor learning 使用的,因為有 label 的 data  可以用來驗證訓練的結果是好還是不好,但是我們這次用到的不論是 LDA 或是 word2vec 都是屬於 unsupervised learning 沒有一個明確的基準點可以驗證,因次不適合用 cross validation 來找出最佳的 hyper parameter 。



那LDA 可以調的參數有哪些些呢?如下圖所示,主要是 K (topic number) , max iteration,doc Concentration和 topic Concentration,不過上網看了許多論文和討論,似乎影響最大的還是K 值。




原本以為只要把這些參數排列組合,找出最大 likelihood 或最小的 perplexity 結果居然看到以下的討論......



在研究中產生許多問題,順便把問題整理在這裡:

1. LDA 跟 word2vec 的差異在哪裡?

LDA 注重的是文章與文章間所有詞的關係,而word2vec 是詞與某篇文章上下文之間的關係,也就是說 word2vec 並沒有考慮語法層面的訊息,一篇文章被看成文字序列(word sequences),只考慮詞與詞之間的位置與邊界關係。

網路上找了一個有趣的解釋,假如你輸入HTC:

普通的word2vec 會找到:Android,cellphone,Taiwan,Google...
但是考慮語法後:Moto,Apple,Nokia,Xiaomi...

雖然看起來都有關連,但是本質上卻是不一樣,真得好難啊....

更多網路資訊:

關於LDA 與 Spark 相關文章:


 





2018年2月14日 星期三

The art of system thinking 談要如何改變系統



本週萬維鋼精英日課介紹的新書是 The Art Of Thinking In Systems: Improve Your Logic, Think More Critically, And Use Proven Systems To Solve Your Problems - Strategic Planning For Everyday Life ,好在有了之前的基礎研究,對於聽懂這些題目輕鬆多了,有興趣的朋友可以看看我之前整理的介紹 - 什麼是系統思考

對於系統思考的理解也有分幾個層次,首先你要先知道它的存在,然後再能找出其中的反饋迴路,進而能辨識基模,最難的就是解決系統問題。

而改變系統性的問題又有三種等級的做法(上中下策)
  • 下策是直接命令。想要什麼就直接要,反對什麼就直接禁止。 (這就是根本沒系統思維)
  • 中策是間接刺激。找到系統中的一個平衡反饋回路,讓回路鬆弛一下。(經濟學常用手法)
  • 上策是尋求一個新的共識。在這個新的共識上,把全社會團結起來去做一件事。 (這讓我想到ICA 在做的事)
找出系統的Reinforcement loop (RL),透過尋求共識的方法去移除或削減RL,說起來很簡單,不過卻是多麼困難的問題啊...可惜沒辦法要求政治人物要選舉前必須通過系統思維的考試,才有資格參與政策制訂。

有趣的是在這本書把系統思維也比喻成冰山,讓我不禁想到薩提爾的冰山理論,我們看問題是不是都看到問題的表象(行為),能否找出夥伴的行為模式與盲點,最後能給予引導解決盲點,這不也是一種系統性思維?



許多理論背後的核心都是相通的(因為都是要解決人的問題?),越來越可以體會到咱們 #敏捷魔藥師 在調藥時的快感(咦)

#萬維鋼的精英日課
#TheArtOfSystemThinking