[通識] 文明的進程 Week 10

重大體悟

羞恥重要的性質是在行為舉止後對於 自我優越感下降 恐懼 ,個人害怕喪失他人的尊重,思考這些帶來的可能性,也就是羞恥情感!其實活得身分低下、與那些自認不同的人處於相同地位。

學了半學期羞恥,這時才發現那吞噬信心的巨獸- 羞恥 ,不知道何時開始,它就像常駐技能似的,不管睡著還醒著都沒有關閉的跡象,這樣活著像遊戲 BUG 似的存在,那麼地與眾不同。

也許,早在那年發現自我弱點時,就烙上那 奴隸的印記 ,不斷地想要遮掩身分的不同,隨時隨地都要小心祕密被發現,想到個人價值有可能在一夕崩落,羞恥感壟罩整個心頭。其實我就是那身分低下的奴,不斷地遮掩印記,卻試圖想要往那更高層爬去。

既然都爬到這,還不想崩落、還不想被發現,至少還要在某些人中存有價值,帶著罪惡感不斷輪迴,也因此走了自己最不想走的路,但是不這麼做,自我價值就在瞬眼之間消散。

如今,崩落假想也隨之成長,直到那再也無法遮掩自己的脆弱前,假想帶來的恐懼不斷地侵蝕我。

回過頭來

段考檢討

寫點與印象答案比較不同的,總之能想到自己很多是零分面向的作答,無知就是我的本體。

  • 為何 淡定 hold 住 的情感為何在中世紀比較沒有呢?
    中世紀的人必須野蠻,對人的關係不是 朋友就是敵人 ,任何一點猶豫將把自己處於不利地位,為了生存,這些克制自我的情感將成為阻礙。
  • 解釋 內心世界 為何而生?
    隨著文明化,人與人之間的關係相當重要,在 人際互動 的親密下,考慮遠程利益,不斷地盤算要做出甚麼樣的決策,才能最適應未來、現在的人際網路,也因此要表現出那衝突、矛盾的思緒都會在內心世界中。
  • 對於中古世紀以及現代教育對於 兒童教育 的方針有何基礎的不同?
    中世紀的兒童教育,兒童就是小大人,什麼都必須知道、什麼都能做,因為它們要趕快成為大人。相對於近代,防止被帶壞、很多不能學、不能知道,不斷地隔離成人的內容。
  • 為什麼機場配置的「紅外線水龍頭」高科技廁所是一個文明化的象徵?
    隔離人與人之間的接觸,同時也是在衛生觀念的防病、防疫措施。隔絕彼此已經作為一個文明化的指標。

本周課程

本周圍繞的主題為社會結構與人際關係,不過說是禮儀與社會結構之間交互關係也可,作為階級區隔,人與人之間所需的禮儀也會有所不同。

曾經說到階級流動與禮儀之間的關係,在不同階級下,人的生活型態不同,面對不同的環境就需要不同的禮儀,即使是在相同時空下,對人制宜也是相當重要的!

階級競逐

作為看待一個社會階級流動,正因為流動的存在,也會形成激烈的競逐,而作為競逐的項目也會隨著年代、國情不同而有所變化,從文憑、車款、養生、 … 都能見得。在傳統社會的世襲中,階級也許不太變化,權貴般的生活到了現代,如果把自己家境多有錢拿出來凸顯階級,也許還比不上一個有品味、氣質、風度的平民百姓。

你的強大若無法帶給別人恩惠,充其量就是個異類。

不過從印度婆羅門教、種姓制度看來,用了一個宗教藉口使得人們相信此生所為將決定下個人生的階級,某些手段利益看來,相當高明呢!社會看起來肯定相當安定,各盡其職。如果沒有太離譜的表現,制度當初為了血統純正的說法,就能達到目標。

結構改變

當社會結構改變時,帶動的是許多職業的消失。當然在科技的發展下,也不少職業消失,而這些人去了哪裡?又有甚麼樣的心理狀態改變?

曾想過自己一身技能,在一個事件動盪下一文不值嗎?接著又要何去何從,找到自我價值?

細看武士階級的年代,其實那段日子在早些時間都消失,他們練就一身武藝,卻沒有在年代中獲得需要、找到工作,不管是在西方騎士、東方武士都有相同的處境,即使後來在重要人士旁進行護衛工作,但身分地位上也有所轉變,至少在禮儀上也必須相對於在戰場上那樣的狂野,轉為平靜的心態。

在中國歷史角度看來,從諸侯分權到王權獨大,武力霸權帶來的壟斷、和平,卻也造成武士們再也沒有表現的機會,何處才有戰場讓咱們逞逞威風?每天面對帝王鞠躬盡瘁,哪適合咱們?也因此不少人從國民崇拜的英勇武士落魄到連下一餐都找不到,即便現在沒了戰場,也要秉持著武士精神度日!絕不能讓別人看到自己軟弱的地方!

講到這,講到動物也有此特性,再凶猛的動物即使自己受傷處於弱勢,若展現脆弱的一面,也會受到反撲。

在西方歷史中,最有印象的是具有領土的貴族們,當商人興起,開始擁有大把大把鈔票時,農地生產不及鈔票來得有價值,金錢觀念勝過於階級,貴族們也無法守住自己的農民,最後要倚靠皇宮的保護,最後遺失自己的自由。「 雖然窮,但我們自由。 」這一詞也在某些勵志的文章中見到,金錢的重要性還是看個人操守吧。

投票是什麼?「有錢有勢的人動員沒錢沒勢的人進行大規模支持活動」-老師一語,全堂竊笑。

到了現代,仍然有許多國家存有兩極化,例如 墨西哥 貧民窟,上網搜尋的結果,還真是一線之隔,可謂「 住得近、習相遠 」老師的意思可能不是這樣,在分工體系下,人們從自給自足轉變到相互依賴,開始有了密切交易,同時也帶來緊張氣氛。

達爾文獎:「讓自己愚蠢的基因不再自由地傳播出去」,對人類的演化做出了貢獻。亦有人認為,達爾文獎是用來記錄「那些在演化過程中走得最慢的人們」。

內心世界

在現在的人情交易所中,深思熟慮、自我克制、精確調整情緒成為交易所的基礎籌碼,只要拿著這些籌碼去,多少能搏得人情網路,同時了解人情網路的拓樸關係,有助於思考站於哪個地位進行支持,可謂拓樸學的二分圖、三分圖之類的關係呢!一個人改變關係,可能標染都要更動!

我們將會變成一個縝密分析的生物,就為了站在有利的位置上,不斷地將訊息解析,否則無法立於社會中。必須知道情感用事也無法撼動這個世界,世界道理不依個人意志運作。

作為這一點,如果一個人思考的太多,針對、多角式、深入剖分的思考會不會造成反應速度的延遲?意即聰明到跟笨蛋似的。

國人特有現象,在一般常理下,自己做出脫格行為將會為自己帶來羞恥,對於別人做的,則會身感難堪,但是我們似乎更進化了?會感到憎恨。

Read More +

自然語言處理 論文研讀 1

Introduction

語意分析涉及正反意見在文字語句中判定,因此必須使用多方視角看待問題與答案,這一點在之前,有人做過意見導向的資訊萃取、資訊摘要 (於文件、語句、片語)。語意分析通常分為三個階段, 校準 辨識 分類 所有已經讀取的文句。這篇論文探討文件分級 (document-level) 的分析,將會著重分析 特定類型的評論文件

第一個問題-極性分類 (polarity classification),對於目標決策正極性 (贊同) 或者是 負極性 (反對),最近也在擴大到中性文件的分類上,雖然研究成果相當多且廣,極性分類仍然是自然語言處理系統中重大的挑戰。

接著將會著重於語言學上的極性分類。在語言學中,建立一個高校的極性分類透過:

  • high order n-grams
  • 複合形容詞,例如 happy 被視為正,而 terrible 視為負面。
  • 詞彙的相依關係
  • 來自於中立文件中所描述的詞組

… 本文略

主要是極性分類,反映正反兩方兩種評論,為了增加精準度,其一種方法把單純闡述事實的評論去除、以及在中性評論用的用詞特別處理,接著對於形容詞與關聯名詞做統計,確保面向的評論對象是所需。

至於 n-gram 部分,有說明到 n 越大,將會造成模糊範圍增加,這樣一來其極性價值就會被削減,對於精準度是會掉的,只用 n = 2 好不好?他說他複合使用 n = 2 和 n = 3 將精準度提升,看到所謂顯著 2% 上升,似乎跟誤差無仿。

Read More +

[通識] 文明的進程 Week 9

心得

請閱讀 梁文道:媚俗,並寫出:你覺得台灣媒體中最常出現哪些情感字眼?反映了怎樣的情感專制呢?(100字)

文章中描述有關 激動 動情 兩字的使用,呈現一種媚俗的表現,

媚俗(德語:Kitsch)是一種被視為次等的視覺藝術形式,對現存藝術風格欠缺品味地作複製,又或是對已獲廣泛認同的藝術作毫無價值的模仿。
媚俗這個概念最初所描述的一類藝術作品,是對19世紀在美學上傳達誇張的傷悲和情緒的藝術手法(例如通俗劇)的一種回應,所以,「媚俗藝術」和「傷感藝術」有密切關係。

那篇文章是在 2010 年寫的,至今也有 4 年多的時間,而現今正在選舉當頭,而在經歷食安風暴的那段日子,新聞中最常出現的一詞為 痛批 ,這一詞是由新聞媒體創造出來的,在其他文本中是沒有任何中文字詞解釋。

其實這一詞等同於 回應 ,但是又增添了情感上的強化,呈現一種委屈、於心不忍的回應,有一種 明明對你這麼好,為什麼你居然這麼對我 。儘管當事者並沒有這樣的情感,但仍然是作為為某些族群發聲的言論,亦或是一種包裝罵人的態度。

越來越少見到苛責、辱罵、… 等,一種單方面說明對方不好之處, 痛批 一詞給予發言人背景、地位,讓人覺得他說話必然有其理由、逼不得已說出這樣的話來。

直接地情緒化辱罵的發言,都將用 痛批 來包裝過於單一情緒化不理智的發言,也就是課程講的內容,我們再也無法直視情緒,任何不理智的情緒都必須被美化成另外一種較為平靜的情感。

Read More +

[通識] 文明的進程 小考集

好幾題都 0 分,也許只是相性不合。而我也只是寫寫我的回答,沒有什麼標準答案。

Week 1

  1. Brad 小學時的校長做了一件甚麼事情讓 Brad 終身難忘?
    讓 Brad 參加音樂會,在音樂會的最後上台自白疾病的原因與如何面對,受到同學們的認同與理解。

  2. Brad 的父親最後幫學校圖書館建書櫃,還送 Brad 甚麼當作和解的禮物?
    一頂工地安全帽。

  3. Brad 接電話時為什麼總是先說自己養了狗?
    因為妥瑞症引起的聲音有如狗吠一般,先避免對方猜疑發生了什麼。

  4. Brad 說他也有閱讀困難,是怎麼樣的困難?
    無法控制自己的脖子不時擺動,使得無法長時間專注於書本內容。

  5. Brad 對於進入那些公共場合有所顧忌?為什麼?
    圖書館、教會、電影院、音樂會。因為那而的人們必須保持固定的儀態和禮貌。

Week 2

  1. 哪個特質不屬於現代心靈:(1) 顧忌他人觀感 (2) 喜怒形於色 (3) 觀察盤算對方。
    (2) 喜怒形於色。(1)(3) 都有著抑制自我生物本能、顧及他人的模式,(2) 則沒有。

  2. 中世紀餐桌上最不常見的餐具是? (1) 主餐盤 (2) 刀子 (3) 叉子
    (3) 叉子。刀子與主餐盤為餐點必備的工具和器材,而叉子是用來區隔他人食物而存在,當時物質不豐裕的情況下,算是奢侈地存在。

  3. 為什麼 Erasmas 在禮儀書中判斷「用餐時胡吃海塞」是鄉巴佬的行為?
    原本作答為 有如飢餓的野獸,為了區隔人與野獸的差別。 0 分
    行為不得體,沒有顧及他人的觀感,鄉巴佬總是做這些事情。(應該類似於這種回答?)

  4. 人際互動的「文明化」如何有助於科學研究方法的發展?
    原本作答為 文明化的互動反應物質生活與當時文化的流行,是一個直接的證據。 0 分
    人際互動的行為反應社會階級結構,藉此了解結構進行研究。(應該類似於這種回答?)

  5. 越是自命文明的人就越容易對他人的舉止感到「不舒服」為什麼?
    原本作答為 因為認為禮儀與自己相同才算文明,舉止不同的他人只會像野獸。 0 分
    階級高低的差別反應在舉止,因此在對於不同階級的人感到厭惡,也等同於對別人行為感到不舒服。

Week 3

  1. 中世紀貴族用餐最可能出現的菜色是:牛排、無骨鴨胸肉、全羊?
    全羊。當時還沒有食物幕後處理的概念,之後才有避見死相的道德感。

  2. 中世紀禮儀最不可能反映的是:身分階級、個人偏好、家庭背景?
    個人偏好。當時禮儀與階級有關,不會涉及強調個人。

  3. 文藝復興禮儀書最不可能說的是:不可粗俗、注意衛生、迴避不雅?
    原本作答為 衛生是後期科技進步,才用衛生理由取代粗俗的理由。 0 分
    注意衛生。當時講就是顧及別人,從不可粗俗、迴避不雅中可以發現都在顧及別人的觀感。注意衛生是在民主平等後,階級不重要,顧及自己才更有約束力。

  4. 就食物的準備而言,為何西方人覺得中華文化的飲食方式很「文明」?
    因為食物會經過多道手法,讓食用時看不出原貌,並且便於入口。不用吐骨。

  5. 這兩張「最後的晚餐」,哪張場景看起來年代較早?你的理由?
    第二張較早,因為沒有個人的餐具。晚期的餐具才比較普及。

    居然有藝術類型學生答題,根據畫風的不同來判斷年代 … 等,給這專業跪了,不過想必是 0 分

Week 4

  1. 文藝復興時期常常提醒人們「天使無所不在」,目的是什麼?
    在不需要顧及他人的需求時,仍要遵守禮儀的理由。

  2. 禮儀書說,便後從廁所回到社交場合時,不能讓人看出洗過手,為什麼?
    會讓場合的人因濕淋淋的手而想起廁所的那些汙穢。(備註:早期甚至希望不洗手。)

  3. 台北捷運地上劃的排隊等候線,其實不是 高度文明 的標誌,為什麼?
    因為需要外物的約束,如何不需要線就能遵守,表示規則內化,那是更文明。

  4. 為何用禮儀書來提升自己氣質的人,反而暴露自己階級地位不高?
    原本作答為 禮儀書的存在是在階級流動的幫手,教導低階級融入上層階級。 0 分
    教導階級高的社為人士的行為模式,正因為需要學習,才表示自己不處於上層階級。

  5. 就 Elias 而言,為什麼社會越文明,其兒童與成人之間的差距就越大?
    成人的禮儀要求越高,兒童在短時間內無法對百年禮儀融會貫通,而這只是相對差距。

Week 5

  1. 在課程 ppt 中,老師用多重比基尼泳裝的貓咪來嘲諷什麼?
    原本作答為 沒有必要這麼遮遮掩掩,一個母親的象徵竟被當作情色。 0 分
    過度地遮掩身體、過度道德化的結果。

  2. 以下何者 不是 社會歷史發展的結果?(1) 哈欠 (2) 洗手 (3) 掩鼻 (4) 遮體。為什麼?
    打哈欠一直都是生物自然反應。其餘皆為後天環境影響而做的事情。但是打哈欠用手遮住也算是後天教育而成。

  3. 為什麼當前的清涼穿著其是 不是 世風日下,而是文明化成功的象徵。

    世風日下:社會的風俗習慣日漸澆薄,每況愈下。(答題時根本不知道這個詞什麼意思。)

    原本作答為 因為向別人暴露身體原本是羞恥的事,面對自己身體不怕外人注目,是心靈上的昇華,外表遮掩不是限制。 0 分 (生物本能不就是要遮掩自我弱點嗎?)
    因為環境影響,代表治安好,不會有鹹豬手的人出現,因此才敢做出清涼穿著。

  4. 「人生:就是成人的生活」這個信念對於中世紀的兒童教育有何引響?
    原本作答為 讓兒童失去原本應有的童年,更早步入成人階段,沒有純真無潔的思想,都被羞恥的教育而想太多什麼不能做的事情。 0 分
    很多事情不能去做、不能去想。因此很多事情也不知道後果的嚴重性。

  5. 文明的 硬體技術 可以使得羞恥情感固定下來,請舉一個例子說明。

    那時卡在硬體設備與軟體技術,兩個弄在一起時,一直想不到那是什麼鬼,於是在被迫交卷前亂填答案。結果只是單純講硬體設備。

    廁所。利用大量的裝飾、氣氛,來隔絕與生物的排泄行為的聯想。

結語

被助教寫了 沒掌握本課程關鍵重點 沒有吸收 。我不否認,好幾堂課還在想算法分析。

Read More +

自然語言處理 - HW02

編譯環境

Dev-C++ 5.6.3

作業內容

給予 5000 筆的亞馬遜書店評論,每一個評論都已經分類好,總共有五種類型的書評,分別為 book, dvd, health, music, 以及 toys_games

利用這 5000 筆分類好的書評寫一個分類器,接著讀入另外測試資料,測試資料每一個書評有既定分類,使用分類器判斷是否符合既定分類,分別計算對於每一種分類書評的準確度 (Accuracy) 和精準度 (Precision)。

  • 準確度:接近正確答案的機率,在這裡可以理解為分類出來的結果等於實際結果的機率。
  • 精準度:測試結果一致的機率,在這裡可以理解為分類出來的結果中,實際上是正確的機率。(是否集中於某個實際結果)

還有一個混用準確度和精準度的概念 f,假設準確度為 R,精準度為 P。

$$F = \frac{1}{\alpha \frac{1}{P} + (1 - \alpha) \frac{1}{R}} = \frac{(\beta^{2} + 1) PR}{\beta^{2}P+R}$$

所謂的 F1 定義為 $\beta = 1, \alpha = 1/2$,最後得到 $F = 2PR / (P+R)$

關於輸入輸出資料

  • gold_standard.xml : 黃金標準的 5000 筆評論
  • test_outcome.xml :原本認為是 測試用的反饋資料,用來檢測寫的分類器好不好。 後更正為助教的分類器跑出來的結果。

通常會拿到一大筆資料,經驗上 3/4 的資料會拿來訓練,剩下 1/4 會拿來檢測。也就是資料量於 3 : 1,至於一段資料怎麼切分有很多方式,可以擷取中間一段的 1/4 … 等都可以。

看一下 xml 格式

gold_standard.xml
1
2
3
4
5
6
7
8
<RDF rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Text category="music">Forget the fact that despite the grumbling
about today's "music" ...</Text>
<Text category="health">Printed all over the box are the words
"with infrared heat". ...</Text>
<Text category="music">I just finished seeing the movie and loved
the song at the end ...</Text>
...

看起來最多兩層,如果不用插件來解析 XML,遞迴處理寫一個 parser 應該不是問題。

於是就這麼蠻幹 XML parser 下去,仔細查閱一下給定的 XML,會發現文件中有 &amp;amp;&amp;amp;quot; 的確在 XML 的元素 content 不會出現 >, < … 等字元,就跟 HTML 的 character entities 一樣都需要被替換成特殊的顯示規格。但真沒有見過上述的那兩個格式,仔細檢查發現應該是對應 and 字串和 " 引號。解析完作 replace 動作。

回過頭來看這次所需要的公式:

$$P(c) = \frac{N_{c}}{N} \\ P(w|c) = \frac{count(w,c)+1}{count(c)+|V|} \\ P(c|s) = P(c) \prod P(w_{i}|c)$$

參數說明:

  • $P(c)$ 表示該分類佔有群體的機率,也就是在 5000 筆評論中,分類 c 佔有百分比。$N_{c}$ 表示有多少筆評論屬於 c 分類。$N$ 表示評論筆數,這裡已知 $N = 5000$
  • $P(w| c)$ 單詞 w 在分類 c 的出現機率為何,$count(w,c)$ 單詞 w 在分類 c 中出現的次數,$count(c)$ 屬於 c 分類中字詞總數 (評論總共有多少字),$| V|$ 分類 c 中使用的單詞集合大小。
  • $P(c| s)$ 評論句子 s 在分類 c 的機率為何。

隨後找 $P(c| s)$ 機率值最大作為分類依準。

最後要找到分類是否正確,對於每一種分類 c 會得到表格

實際結果\分類結果 Classifier no Classifier yes
Truth no true negative(TN) false positive(FP)
Truth yes false negative(FN) true positive(TP)

準確度 R 意即:TP / (TP + FN)、精準度 P 意即:TP / (TP + FP)

對於 Micro-average 和 Macro-average 的計算,Micro 和 Macro 概念上我理解程式幾何平均和算數平均的概念,Micro 會把每個分類 c 的表單結果累加到一個表格,隨後按照一般分類算法計算準確和精準度,而 Macro 則是將每個分類算完的結果取算術平均。

代碼

傻傻地用分類器判斷與助教的決策比較的運行結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
process gold_standard.xml ...
statistics model built ...
--------------------+----------
book | 1000
dvd | 1000
health | 1000
music | 1000
toys_games | 1000
--------------------+----------
process test_outcome.xml ...
testing test_outcome.xml ...
| AC\Assign| book| dvd| health| music|toys_games|
| book| 892| 29| 17| 9| 25|
| dvd| 22| 829| 16| 48| 41|
| health| 30| 19| 975| 46| 177|
| music| 5| 13| 12| 870| 28|
|toys_games| 10| 16| 43| 21| 807|
book
p :0.9301355579
r :0.9176954733
f :0.9238736406
dvd
p :0.9150110375
r :0.8671548117
f :0.8904403867
health
p :0.9172154280
r :0.7818765036
f :0.8441558442
music
p :0.8752515091
r :0.9375000000
f :0.9053069719
toys_games
p :0.7486085343
r :0.8996655518
f :0.8172151899
Micro-average
p :0.8746000000
r :0.8746000000
f :0.8746000000
Macro-average
p :0.8772444134
r :0.8807784681
f :0.8790078886
--------------------------------
Process exited after 6.545 seconds with return value 0

後來發現是公式理解錯誤

  • 真陽性 (TP, true positive)
    正確的肯定。又稱:命中 (hit)
  • 真陰性 (TN, true negative)
    正確的否定。又稱:正確拒絕 (correct rejection)
  • 偽陽性 (FP, false positive)
    錯誤的肯定,又稱:假警報 (false alarm),第一型錯誤
  • 偽陰性 (FN, false negative)
    錯誤的否定,又稱:未命中 (miss),第二型錯誤

準確度就是在正確答案中找誤判,而精準度就是在判斷正確下找錯誤。

後來實驗用 gold_standard.xml train 和 test,運行結果為

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| AC\Assign| book| dvd| health| music|toys_games|
| book| 950| 7| 15| 3| 25|
| dvd| 7| 895| 33| 21| 44|
| health| 1| 0| 984| 1| 14|
| music| 1| 3| 15| 968| 13|
|toys_games| 0| 1| 16| 1| 982|
book
p :0.9906152242
r :0.9500000000
f :0.9698825932
dvd
p :0.9878587196
r :0.8950000000
f :0.9391395593
health
p :0.9256820320
r :0.9840000000
f :0.9539505574
music
p :0.9738430584
r :0.9680000000
f :0.9709127382
toys_games
p :0.9109461967
r :0.9820000000
f :0.9451395573
Micro-average
p :0.9558000000
r :0.9558000000
f :0.9558000000
Macro-average
p :0.9577890462
r :0.9558000000
f :0.9567934893

當然不能拿相同的 train 和 test data 來用,但是也明顯地發現,這個 model 仍然沒有辦法達到很高純度的結果,在部分比例中也只達到 90% 的精度。

那有沒有一種情況,我們將六種分類的共同交集字符給去除?這樣的效果會不會比較好呢?例如常用的 Ithinkit … 等,在 model 中直接無視這些常用字集的效果如何呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void custom() {
set<string> common;
int first_set = 1;
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
set<string> s;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
s.insert(jt->first);
if (first_set) common = s, first_set = 0;
else {
set<string> C;
set_intersection(common.begin(), common.end(), s.begin(), s.end(), inserter(C, C.begin()));
common = C;
}
}
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
for (set<string>::iterator jt = common.begin();
jt != common.end(); jt++)
R.erase(*jt);
int cnt = 0;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
cnt += jt->second;
count_category[it->first] = cnt;
}
}

上述代碼為將每一個分類的字集與共同交集,並且將共同交集從每個分類中移除,同時將記數重新統計。根據實驗結果,很多分類都直接噴掉,也許是專有名詞使用的量太少,雖然每個字集仍然有上千上萬不等,但是在分類效應上某些分類完全消失。效果差到不行,所以就直接無視吧。或者提供點意見吧。

回過頭來解一下關於作業內容,其實作業內容可以化簡為:

輸入只有一組測資,該組測資會有數行,每一行上會有兩個分類結果,第一個分類結果為標準答案,第二個分類結果為根據模型運算的結果。對於測資輸出每一個分類的準確度、精準度以及 f1 的數據結果。

兩個輸入檔案可以壓縮為

Input

1
2
3
4
5
6
7
5000
music music
book health
music music
toys_games book
music music
... here are more rows

很明顯地,第二個評論中,誤把 book 類型判斷成 health。

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| AC\Assign| book| dvd| health| music|toys_games|
| book| 907| 25| 48| 7| 13|
| dvd| 35| 873| 43| 24| 25|
| health| 10| 2| 932| 11| 45|
| music| 9| 46| 56| 865| 24|
|toys_games| 11| 10| 168| 21| 790|
book
p :0.9331275720
r :0.9070000000
f :0.9198782961
dvd
p :0.9131799163
r :0.8730000000
f :0.8926380368
health
p :0.7473937450
r :0.9320000000
f :0.8295505118
music
p :0.9321120690
r :0.8650000000
f :0.8973029046
toys_games
p :0.8807134894
r :0.7900000000
f :0.8328940432
Micro-average
p :0.8734000000
r :0.8734000000
f :0.8734000000
Macro-average
p :0.8813053583
r :0.8734000000
f :0.8773348714
--------------------------------
Process exited after 1.736 seconds with return value 0

答案算出來當然跟助教一下啊,知道什麼是 sample output 嗎?在 ACMer 的眼中,代表根據算法不同,答案也許會有誤差,或者是測資不同造成答案不同。而 sample output 通常告訴我們的是輸出格式與可能情況,而非測資的正確答案。

我就是很笨,無法理解這個世界。不知道那檔案是有序對應,看到 attribute 名稱 name 一樣,內容 content 不一樣就自動補完無法理解的英文部分,而沒有去看 tag 中 inner content 內容是相同的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#include <stdio.h>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <sstream>
#include <math.h>
#include <ctype.h>
#include <string>
#include <string.h>
#include <set>
#include <algorithm>
using namespace std;
class XMLParser {
public:
struct Node {
string tag_name, content;
map<string, string> attr;
vector<Node> child;
};
Node root;
XMLParser(string text = "") {
sin << text;
root = Node();
build(root, "");
}
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
string html2text(string s) {
string ret(s);
replaceAll(ret, "&amp;amp;quot;", "\"");
replaceAll(ret, "&amp;amp;", "and");
return ret;
}
private:
stringstream sin;
void getTagContent(Node &u) {
char c, div;
while (sin.get(c)) {
if (c == '<') {
while (sin.get(c) && isspace(c));
u.tag_name = c;
while (sin.get(c) && c != '>' && !isspace(c))
u.tag_name += c;
if (c == '>') return;
while (true) {
while (sin.get(c) && isspace(c));
if (c == '>') return;
string a = "", b = "";
a += c;
while (sin.get(c) && !isspace(c) && c != '=')
a += c;
while (sin.get(c) && (isspace(c) || c == '"' || c == '\'')) div = c;
b += c;
while (sin.get(c) && !isspace(c) && c != div)
b += c;
u.attr[a] = b;
}
return;
}
}
}
int build(Node &u, string last) {
getTagContent(u);
if (u.tag_name == last)
return 0;
while (sin.peek() != EOF && sin.peek() != '<') {
char c;
sin.get(c);
u.content += c;
}
u.content = html2text(u.content);
while (sin.peek() != EOF) {
while (sin.peek() != EOF && isspace(sin.peek()))
sin.get();
if (sin.peek() == '<') {
u.child.push_back(Node());
if (!build(u.child[u.child.size() - 1], "/" + u.tag_name)) {
u.child.pop_back();
break;
}
}
}
return 1;
}
};
class StatsModel {
public:
map<string, map<string, int> > categories; // count(w, c)
map<string, int > commentCount; // N_{c}
map<string, int > count_category; // count(c)
map<string, map<string, int> > judgeTable;
int N, V;
int microtable[2][2]; // [truth 0:1][classifier 0:1]
StatsModel() {
N = V = 0;
memset(microtable, 0, sizeof(microtable));
}
vector<string> normalSentence(string content) {
vector<string> w;
stringstream sin(content);
string token;
while (sin >> token) {
token = igntrim(token);
token = str2lower(token);
if (token.length() > 0)
w.push_back(token);
}
return w;
}
void recordJudge(string truth, string classifier) {
judgeTable[truth][classifier]++;
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
int t = (it->first == truth);
int c = (it->first == classifier);
microtable[t][c]++;
}
}
string judgeComment(string category, string content) {
vector<string> w = normalSentence(content);
double Pc, P;
double maxPwc = - 1e+30;
string chooseClass = "";
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
Pc = (double)it->second / N;
P = log(Pc);
map<string, int> &R = categories[it->first];
int count_c = count_category[it->first], count_w_c;
for (int i = 0; i < w.size(); i++) {
count_w_c = 0;
if (R.find(w[i]) != R.end())
count_w_c = R[w[i]];
P += log((double) (count_w_c + 1)/ (count_c + R.size()));
}
if (P > maxPwc)
maxPwc = P, chooseClass = it->first;
}
recordJudge(category, chooseClass);
return chooseClass;
}
void addComment(string category, string content) {
commentCount[category]++, N++;
map<string, int> &S = categories[category];
vector<string> w = normalSentence(content);
for (int i = 0; i < w.size(); i++)
S[w[i]]++;
count_category[category] += w.size(), V += w.size();
}
string igntrim(string s) {
while (s.size() > 0) {
if (isspace(s[0]) || s[0] == '.' || s[0] == ','
|| s[0] == '!' || s[0] == '"' || s[0] == '\'')
s = s.substr(1);
else {
int t = s.length();
if (isspace(s[t-1]) || s[t-1] == '.' || s[t-1] == ','
|| s[t-1] == '!' || s[t-1] == '"')
s = s.substr(0, t-1);
else
return s;
}
}
return s;
}
string str2lower(string s) {
for (int i = 0; i < s.length(); i++)
s[i] = tolower(s[i]);
return s;
}
void custom() {
set<string> common;
int first_set = 1;
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
set<string> s;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
s.insert(jt->first);
if (first_set) common = s, first_set = 0;
else {
set<string> C;
set_intersection(common.begin(), common.end(), s.begin(), s.end(), inserter(C, C.begin()));
common = C;
}
}
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
for (set<string>::iterator jt = common.begin();
jt != common.end(); jt++)
R.erase(*jt);
int cnt = 0;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
cnt += jt->second;
// printf("%d -> %d\n", count_category[it->first], cnt);
count_category[it->first] = cnt;
}
// printf("%d\n", common.size());
}
void print() {
printf("%-20s+%10s\n", string(20, '-').c_str(), string(10, '-').c_str());
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
printf("%-20s|%10d\n", it->first.c_str(), it->second);
}
printf("%-20s+%10s\n", string(20, '-').c_str(), string(10, '-').c_str());
}
void report() {
// print <judge table>
printf("|%10s|", "AC\\Assign");
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++)
printf("%10s|", it->first.c_str());
puts("");
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
printf("|%10s|", it->first.c_str());
for (map<string, int>::iterator jt = commentCount.begin();
jt != commentCount.end(); jt++) {
printf("%10d|", judgeTable[it->first][jt->first]);
}
puts("");
}
// homework format
// recall: fraction of docs in class i classified correctly
// precision: fraction of docs assigned class i that are actually about class i
const double beta = 1;
double micro_r = 0, micro_p = 0, macro_r = 0, macro_p = 0, f1;
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
double recall = 0, precision = 0, f1 = 0;
int sumr = 0, sump = 0;
for (map<string, int>::iterator jt = commentCount.begin();
jt != commentCount.end(); jt++) {
sumr += judgeTable[it->first][jt->first];
sump += judgeTable[jt->first][it->first];
}
recall = (double) judgeTable[it->first][it->first] / sumr;
precision = (double) judgeTable[it->first][it->first] / sump;
f1 = (beta * beta + 1) * precision * recall / (beta * beta * precision + recall);
macro_r += recall, macro_p += precision;
printf("%s\n", it->first.c_str());
printf("%9s :%.10lf\n", "p", precision);
printf("%9s :%.10lf\n", "r", recall);
printf("%9s :%.10lf\n", "f", f1);
}
// for (int i = 0; i < 2; i++, puts(""))
// for (int j = 0; j < 2; j++)
// printf("%5d ", microtable[i][j]);
// [truth 0:1][classifier 0:1] = { {TN, FP}, {FN, TP} }
micro_r = (double) microtable[1][1] / (microtable[1][1] + microtable[1][0]); // TP / (TP + FN)
micro_p = (double) microtable[1][1] / (microtable[1][1] + microtable[1][0]); // TP / (TP + FP)
f1 = (beta * beta + 1) * micro_p * micro_r / (beta * beta * micro_p + micro_r);
printf("%s\n", "Micro-average");
printf("%9s :%.10lf\n", "p", micro_p);
printf("%9s :%.10lf\n", "r", micro_r);
printf("%9s :%.10lf\n", "f", f1);
macro_r /= commentCount.size();
macro_p /= commentCount.size();
f1 = (beta * beta + 1) * macro_p * macro_r / (beta * beta * macro_p + macro_r);
printf("%s\n", "Macro-average");
printf("%9s :%.10lf\n", "p", macro_p);
printf("%9s :%.10lf\n", "r", macro_r);
printf("%9s :%.10lf\n", "f", f1);
}
};
int main() {
ifstream fin("gold_standard.xml");
string xml = "", line;
while (getline(fin, line))
xml += "\n" + line;
printf("process gold_standard.xml ...\n");
XMLParser xmlDoc(xml);
StatsModel statsModel;
printf("statistics model built ...\n");
for (int i = 0; i < xmlDoc.root.child.size(); i++) {
string a = xmlDoc.root.child[i].attr["category"],
b = xmlDoc.root.child[i].content;
statsModel.addComment(a, b);
}
statsModel.print();
// statsModel.custom();
ifstream tin("test_outcome.xml");
xml = "";
while (getline(tin, line))
xml += "\n" + line;
printf("process test_outcome.xml ...\n");
XMLParser testDoc(xml);
printf("testing test_outcome.xml ...\n");
for (int i = 0; i < testDoc.root.child.size(); i++) {
statsModel.recordJudge(xmlDoc.root.child[i].attr["category"], testDoc.root.child[i].attr["category"]);
}
statsModel.report();
return 0;
}
Read More +

[通識] 文明的進程 Week 6

公私領域的分裂,在不同的場合下,擁有的心理、情緒反應會有所不同。在某些場合 渴望愉悅 是必要的行為,抑制住反而有失禮儀。相反地, 否認愉悅 也是有場合是必須的。例如在家裡與在社交場所,在家裡可以因為有家人關係,表現得自然不過,如果什麼都抑制住,反而稱不上家人相處。而在社交場所,即使討厭一個人,也不能在臉上表現出來。

比中指 辱罵別人其實是很文明的舉止,因為並沒有實施暴力行為,是一種克制自我的行為。然而,比中指仍然稱不上是好的禮儀,但已經進步很多。

裸體代表的就是 自然 本相 ,查看其背後的涵義,這在很多理論上作為依據-抗議的主旨。 求自然 求真相

關於小組報告的大綱如下:

  • 為什麼主題有關文明化?
  • 看時間軸中,行為是怎麼形成的?
  • 約束人們做了哪些事情,思考了那些事情。
  • 約束-身分-環境,三者彼此之間的相互關係。
  • 在不同的時空背景下,又有什麼差別?是甚麼原因造成的?

特別注意報告要點:

  • 請說大家沒想過的,觀眾都等著你給的 surprise

本周報告

無處不在的文明教育(家庭、學校、公共空間與媒體)

家庭

談什麼?不談什麼?

首先是性教育、生與死,小時候不談這些,但隨著長大成人就會依依序序跟家裡長輩們談談,關於性、生後事 … 等一些比較嚴肅的話題。

看不看 A 片?寫不寫遺書?A 片的命名如何文明化?

PTT A片取什麼名字最安全?
大陸尋奇、舌尖上的日本、微積分、幫爸爸抓的、流體力學、日文初級音聽檢定 … 等

最後老師特別贊助:取名為 文明的進程

學校

環保意識的培養?

其實我認為學校文明教育從蔣公那時開始到現在就很有不同,學三民主義的課程到現在九年一貫課程,中間經歷了相當多的轉變。老一輩的人三民主義的日子,學著書上的精神,造就他們的價值觀。而我們學習到的只有宏觀歷史,而少了點歷史仇視,沒有嚮往開國元老,敬重政治人物的努力。

小學從品德教育開始,在國中之後便不怎麼有時間上這些,原本有 上,變成用條例規範,逐漸地,我們可以開始閱讀 規則 並且知道要遵守。

公共空間與媒體

媒體很有趣,從小看到大,可以說是一個群體訓練場,看著畫面猜著下面給的標題是否符合,已經快要變成一場遊戲,只要八九不離十,就有十足把握出門跟別人談談這些。在一個單向的管道中,從媒體為何而來?人們疏離開始說起,又或者不想跟別人談這個主題,需要一個媒介替你轉達!

Read More +

計算幾何 - 期中考練習

  1. (15 points total)
    a. (10 points) Given a set of points that are presorted by their x-coordinate value, provide an algorithm that computes the convex hull of these points in O(n).
    b. (5 points) If more than 2 points are possibly on an edge of convex hull, explain briefly how your algorithm handles this case.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int cross(Pt o, Pt a, Pt b) {
return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
int monotone(int n, Pt p[], Pt ch[]) {
sort(p, p+n);
int i, m = 0, t;
for(i = 0; i < n; i++)
while(m >= 2 && cross(ch[m-2], ch[m-1], p[i]) <= 0)
m--;
ch[m++] = p[i];
for(i = n-1, t = m+1; i >= 0; i--)
while(m >= t && cross(ch[m-2], ch[m-1], p[i]) <= 0)
m--;
ch[m++] = p[i];
return m - 1;
}

會將三點一線段的中間那一點替除掉,直到一個線段上只經過兩個點。

  1. (20 points total)
    a. (5 points) What are the types of event points in the plane sweep algorithm for line segment intersection problem?
    b. (10 points) Explain briefly when each type of event points is inserted to the event queue. Create a simple example (with 2 line segments) to demonstrate how it works.
    c. (5 points) When will the plane sweep algorithm for line segment intersection problem not suitable? Give a quantitative answer (i.e., describe your answer by using the Big-O notations). In addition, why is applying plane sweep algorithm on subdivision overlay in general a good idea?

  • 掃描時遇到的三種情況
    1. 碰到開始的左端點 (加入此線段)
    2. 碰到結束的右端點 (移除此線段)
    3. 碰到線段之間的交點 (預測下個最近的相交點後,將其包含這個交點線段移除後,重新加入)
  • 很簡單的,請參考上述三種情況繪製。
  • 當交集的數量在 $\Theta(n^{2})$ 的時候,複雜度是 $\Theta(n^{2}log n)$,還不如直接窮舉任兩個線段計算交點 $\Theta(n^{2})$,就算要去重複,常數也比掃描線算法來得低。
  1. (20 points total)
    a. (10 points) Draw a simple polygon with 4 different types of vertices. Mark each vertex with its type. In addition, which two out of these 4 types are NOT allowed in a y-monotone piece?
    b. (5 points) Mark the “helper” for each of the vertices in your part (a) simple polygon that are not allowed in a y-monotone piece.
    c. (5 points) The triangulation of a y-monotone piece (with n vertices) can be done in linear time. Explain briefly why.

  • start, split, end, merge, regular vertex 明明有五種!
  • split, merge vertex 不符合 y-monotone piece
  • 加入 helper,對於 split 而言要往下找 split 或者是 regular vertex 相連,對 merge 而言要往上找 merge 或者是 regular 相連。
  • 因為往左可以根據維護凹性在 O(n) 時間內完成三角化,同理往右走訪。
  1. (20 points total)
    a. (5 points) What is the worst-case time complexity for the algorithm that solves the 2-dimensional linear programming problem?
    b. (5 points) Simplex algorithm is known to solve the linear programming problem in Operational Research. Why don’t we simple apply Simplex algorithm for the 2-dimensional linear programming problem?
    c. (10 points) Let (H, c) be a linear program. We number the half-planes h1, h2,…, hn. Let Hi be the set of the first i constraints, together with the special constraints m1 and m2 (i.e., the bound so that the solution space is limited). Let vi be the optimal point in Hi that satisfies the constraints. Explain why vi = vi-1 if vi-1 is contained in hi.

  • $O(n^{2})$ incremental LP problem,每加入一個半平面,都必須重新計算最佳交集。
  • Simplex algorithm O(n log n),在 2D 限制下,可以做到 O(n)。
  • 其實這是一個廢話,因為 hi 加上去,只會讓最佳解更糟,如果最佳解沒變,那麼最佳解仍然維持。
  1. (15 points total)
    a. (10 points) Briefly explain what a “split node” is. Create a balanced one-dimensional search tree with 8 leave nodes to be “1”, “2”, “3”, “4”, “5”, “6”, “7”, and “8”, and a range query [2, 6] to show where the split node is and how it helps to find all numbers in the range.
    b. (5 points) Both kd-trees and range trees are designed to do range query. Give one scenario that the kd-trees should be used and another scenario that the range trees should be adopted.

1
2
3
4
5
6
7
8
9
[4]
/ \
/ \
/ \
[2] [6]
/ \ / \
[1] [3] [5] \
/\ /\ /\ \
[1][2][3][4] [5][6] [7]

找到其中一邊的 split node 的寫法如下:

1
2
3
4
5
6
v = root
while v is not leaf && (r <= xv || xv' > l)
if l <= xv'
v = lc(v)
else
v = rc(v)

最後我們找到兩個 split node [1], [7],在兩個 split node 之間的葉節點都是答案,對於葉節點可以利用建造時,使用一個 linked list 去完成。

  • 對於多維度範圍查找用 range tree 最好,可以保證在 $O(log^{d} n)$ 以內找到解,kd-tree 在這種情況很容易退化。
  • 對於最鄰近點搜索則是使用 kd-tree 最好,range tree 反而沒辦法支持這種操作。
  1. (20 points)
    a. (5 points) Draw the trapezoidal map of the following given figure. Note that the bounding box is provided already. (Give each trapezoid a number, which will be used in part (b).)
    b. (10 points) Follow the algorithm to construct the search structure D for the trapezoidal map in part a). The segments are inserted in the order of s4, s3, s2, and s1.
    c. (5 points) In the trapezoidal algorithm, the endpoints of line segments are assumed to have different x-coordinate value (i.e., so-called general position). While a method was provided to relax this constraint, explain briefly why the composite-number method (i.e., transform (x, y) to (x|y, y|x)) which has been used in kd-trees and range trees to deal with the similar constraint was not adopted?

  • 因為它們是 range query,對於相同的 x 值仍然要算相同,利用偏斜的效果不利於操作。
Read More +

計算幾何 - HW03

Master Theorem

$$T(n) = \begin{cases} aT(n/b) + n^{c} & \text{ if } n > 1 \\ d & \text{ if } n = 1 \end{cases}$$
  1. $\text{if } log_{b}a < c, T(n) = \theta(n^{c})$
  2. $\text{if } log_{b}a = c, T(n) = \theta(n^{c} log n)$
  3. $\text{if } log_{b}a > c, T(n) = \theta(n^{log_{b}a})$

Extend Master Theorem

$$T(n) = \begin{cases} aT(n/b) + f(n) & \text{ if } n > 1 \\ d & \text{ if } n = 1 \end{cases} \\ E = log_{b}(a)$$
  1. $\text{if } f(n) = O(n^{E} (log_{b}n)^{\alpha} ) \text{ and } \alpha < -1, T(n) = \theta(n^{E})$
  2. $\text{if } f(n) = O(n^{E} (log_{b}n)^{\alpha} ) \text{ and } \alpha = -1, T(n) = \theta(n^{E} log_{b} log_{b}(n))$
  3. $\text{if } f(n) = O(n^{E} (log_{b}n)^{\alpha} ) \text{ and } \alpha > -1, T(n) = \theta(n^{E}(log_{b}n)^{\alpha + 1})$

Chapter 5

5.1

In the proof of the query time of the kd-tree we found the following
recurrence:

$$Q(n) = \begin{cases} O(1) & \text{ if } n = 1 \\ 2 + 2Q(n/4)& \text{ if } n > 1 \end{cases}$$
Prove that this recurrence solves to Q(n) = O(√n). Also show that Ω(√n) is a lower bound for querying in a kd-tree by defining a set of n points and a query rectangle appropriately.

——-

1. by master theorem, $a = 2, b = 4, c = 0 \Rightarrow Q(n) = \Theta(\sqrt{n})$
2. $\Omega(\sqrt{n})$ 是 kd-tree 的 lower_bound。如果 + 號存在的行都一直被執行,另外 - 號行都不會被執行,那麼複雜度就會達到 $\Omega(\sqrt{n})$,要明白如何加上 report 則會更慢,必須將包含的點依序回報。找一個不包含所有點的細長矩形於正中央即可,每次循環切割到 x 時,保證會留下 n/4 個節點。

1
2
3
4
5
6
7
8
9
10
11
12
13
Algorithm: SEARCHKDTREE(v, R)
if v is leaf
report the points stored at v if it lies in R.
else
- if region(lc(v)) contains R
report subtree lc(v)
+ else if lc(v) intersects R
SEARCHKDTREE(lc(v), R)
- if region(rc(v)) contains R
report subtree rc(v)
+ else if rc(v) intersects R
SEARCHKDTREE(rc(v), R)

5.3

In Section 5.2 it was indicated that kd-trees can also be used to store sets of points in higher-dimensional space. Let P be a set of n points in d-dimensional space. In parts a. and b. you may consider d to be a constant.

  1. Describe an algorithm to construct a d-dimensional kd-tree for the points in P. Prove that the tree uses linear storage and that your algorithm takes $O(n log n)$ time.
  2. Describe the query algorithm for performing a d-dimensional range query. Prove that the query time is bounded by $O(n^{1−1/d} +k)$.
  3. Show that the dependence on d in the amount of storage is linear, that is, show that the amount of storage is $O(dn)$ if we do not consider d to be a constant. Give the dependence on d of the construction time and the query time as well.

1
2
3
4
5
6
7
8
9
Algorithm : build(int k, int l, int r, int dep)
if l > r
return NULL
m = (l + r)/2
Node ret = median axis[k%K] of point[l, r] ----- O(n)
split points[l, r] by median ----- O(n), C++ std::nth_element()
ret.lson = build((k+1)%K, l, m-1);
ret.rson = build((k+1)%K, m+1, r);
return ret;
  1. 利用 median of medians 算法找到中位數,數據儲存用指針來完成搜索,不用移動資料。
    以上代碼根據遞迴公式 $T(n) = 2T(n/2) + O(n) \Rightarrow T(n) = \Theta(n log n)$,而 kd-tree 是一個 full binary tree,每一個節點都代表一個實際資料,因此空間複雜度 $O(n)$
  2. 假設在 d 為空間,Q(n) 表示 n 個點的詢問,依序按照維度切割 (ex. x, y, z, x …),現在只關注 x 軸上的切割,假設詢問範圍包含所有的 y, z,那麼在 2ed x 節點中,每一個節點具有 $n/2^{d}$ 資料,而同一層會有 $2^{d-1}$ 個 x 維度的子節點。然後遞迴詢問 $2^{d-1}$ 所包含的範圍查找。
    藉由 master theorem, $a = 2^{d-1}, b = 2^{d}, c = 0 \Rightarrow Q(n) = \Theta(n^{1 - 1/d})$ $$Q(n) = \begin{cases} O(1) & \text{ if } n < 2^{d} \\ 2^{d-1} + 2^{d-1} Q(n/2^{d}) & \text{ if } n \geq 2^{d} \end{cases}$$
  3. 如果 d 不是常數,每一個內部節點空間 O(d),有 n 個節點則需 O(dn) 的儲存空間。詢問上,需要在 intersected 花 O(d) 時間決定是否存在交集、包含,再來判斷是否走訪子樹,因此詢問是 $2dQ(n) = O(dn^{1-1/d})$,加上回報的效率為 $2dQ(n) = O(dn^{1-1/d} + k)$

5.5

Algorithm SEARCHKDTREE can also be used when querying with other ranges than rectangles. For example, a query is answered correctly if the range is a triangle.

a. Show that the query time for range queries with triangles is linear in the worst case, even if no answers are reported at all. Hint: Choose all points to be stored in the kd-tree on the line y = x.
b. Suppose that a data structure is needed that can answer triangular range queries, but only for triangles whose edges are horizontal, vertical, or have slope +1 or −1. Develop a linear size data structure that answers such range queries in O(n3/4+k) time, where k is the number of points reported. Hint: Choose 4 coordinate axes in the plane and use a 4-dimensional kd-tree.
c. Improve the query time to O(n2/3+k). Hint: Solve Exercise 5.4 first.


  1. 最慘情況是 O(n)-詢問範圍為三角形。
    詢問的範圍如圖,所有點落在 y = x 上,三角形範圍是一個很貼近 y = x 的三角形,三角形並沒有包含任何一個點,卻與所有劃分的區域有交集,因此必須走訪所有節點。
  2. 如果要支持三角形範圍查找 (三角形的邊要不垂直、平行、斜率 +1、斜率 -1)。找到一個詢問 $O(n^{3/4} + k)$ 的資料結構。
    類似 kd-tree,但是輪替的標準為 x 軸 y 軸 斜率 1 斜率 -1 ,根據 5.3(b) 的公式,相當於 d = 4 的情況,得到 $O(n^{1 - 1/4} + k) = O(n^{3/4} + k)$
  3. 加快到 $O(n^{2/3} + k)$ 的詢問時間。
    在這裡想到是建立兩個 kd-tree,其中一個順序為 x 軸 斜率 1 斜率 -1 ,另一個順序為 y 軸 斜率 1 斜率 -1 。前者可以回答向上、向下三角形,後者回答向左、向右三角形。相當於 d = 3 的切割,最多拆成 4 個範圍查找,$O(4n^{1 - 1/3} + k) = O(n^{2/3} + k)$
    1. 在詢問矩形時,拆成四個三角形查找 (向上、向下、向左、向右三角形)
    2. 在詢問三角形時,拆成兩個三角形查找

5.9

One can use the data structures described in this chapter to determine whether a particular point (a,b) is in a given set by performing a range query with range [a : a]×[b : b].

  1. Prove that performing such a range query on a kd-tree takes time O(logn).
  2. What is the time bound for such a query on a range tree? Prove your answer.

  1. 對於 kd-tree 所消耗的時間 O(log n) 說明。 $[a:a] \times [b:b]$ 並不會跨區間。在 SEARCHKDTREE(v, R) 函數中,Line SEARCHKDTREE(lc(v), R) 和 SEARCHKDTREE(rc(v), R) 只會有一個符合。
    $$Q(n) = \begin{cases} O(1) & \text{ if } n = 1 \\ 1 + Q(n/2) & \text{ if } n > 1 \end{cases}$$
  2. 對於 kd-tree 所消耗的時間 O(d log n) 說明。
    首先能知道會先在第一維度探訪 $[a:a]$ 的葉節點,中間經過 log n 個節點最後到葉節點,然後在其相對應的 y 軸 tree 中查找 $[b:b]$ 也是 log n。因此是 $O(\sum{i = 1}^{d} log n) = O(d log n)$

5.11

Let S1 be a set of n disjoint horizontal line segments and let S2 be a set
of m disjoint vertical line segments. Give a plane-sweep algorithm that
counts in O((n+m) log(n+m)) time how many intersections there are
in S1 ∪ S2.


給 n 個不相交的水平線段、m 個不相交的垂直線段,在 O((n+m) log (n+m)) 的時間內找到焦點個數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Algorithm:
1. sort all x-coordinate ----- O((n+m) log (n+m))
2. sweep x from small to large, maintain a segment tree or range tree.
for x = -oo to oo
for each horizontal line (sx, y)-(ex, y) in x
if sx = x
1Drangetree.add(y) ----- O(log (n+m))
for each vertical line (x, sy)-(x, ey) in x
ret += 1Drangetree.query(sy, ey) ----- O(log (n+m))
for each horizontal line (sx, y)-(ex, y) in x
if ex = x
1Drangetree.remove(y) ----- O(log (n+m))
return ret

Chapter 6

6.1

Draw the graph of the search structure D for the set of segments depicted
in the margin, for some insertion order of the segments.


雖然沒有加入順序的考量,但是手爆一個 17 個線段、平面空間 29 個的建造 … 也許有點瘋狂,用最簡單的由上而下掃描,造成一個傾斜的樹也是各種不容易。

6.2

Give an example of a set of n line segments with an order on them that
makes the algorithm create a search structure of size Θ(n2) and worst-case
query time Θ(n).


找到一個最慘空間 $\Theta(n^{2})$,最慘詢問時間 $\Theta(n)$

n 個線段,將其中 n/2 放置在同一個水平線上,對於剩餘 n/2 個:

每次加入的順序 s1, s2, …, si,每次的線段的 x 值會包含前一個線段,$s_{i}.lx < s_{i-1}.lx, s_{i}.rx > s_{i-1}.rx$,美加入一個線段,會增加 n/2 個內部節點,並且最大深度增加 1。總計加入 n/2 次,增加的節點數量 O(n/2 x n/2) = O(n^2),深度 O(n/2) = O(n)。

6.5

Given a convex polygon P as an array of its n vertices in sorted order along the boundary. Show that, given a query point q, it can be tested in time O(logn) whether q lies inside P.


由於詢問次數相當多,必須將複雜度降到 O(log n),採用的方式將凸包其中一個點當作基準,則如果在凸包的點而言,一定會落在某個以基點拉出的三角形內部中,為了方便計算,則可以拿外積的正負邊界上。得到可能的三角形後,從邊界中可以藉由外積計算是否同側。

採用射線法 O(n) 肯定是吃大虧的。

part of UVa 12048 - Inhabitants
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
double cross(Pt o, Pt a, Pt b) {
return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
int inside_convex(const Pt &p, Pt ch[], int n) {
if(n < 3)
return false;
if(cross(ch[0], p, ch[1]) > eps)
return false;
if(cross(ch[0], p, ch[n-1]) < -eps)
return false;
int l = 2, r = n-1;
int line = -1;
while(l <= r) {
int mid = (l + r)>>1;
if(cross(ch[0],p, ch[mid]) > -eps) {
line = mid;
r = mid - 1;
} else l = mid + 1;
}
return cross(ch[line-1], p, ch[line]) < eps;
}
Read More +

自然語言處理 - HW01

編譯環境

Dev-C++ 5.6.3

Language model implementation

實作語言處理模型,要求讀入一連串的英文語句做為基底,接著詢問一句的正確性為多少,也就是這句話是正確拼讀的機率為何,算是一個可用的句子嗎?

$$P(w_{i}) = \frac{Count(w_{i})}{\sum_{j} Count(w_{j})} \\ P(w_{i}, w_{i+1}) = \frac{Count(w_{i}, w_{i+1})}{\sum_{j} Count(w_{j}, w_{j+1})} \\ P(w_{i+1}|w_{i}) = \frac{P(w_{i}, w_{i+1})}{P(w_{i})}$$

上述分別是一個單詞的機率,以及計算相鄰兩個單詞的機率,最後推估在這個單詞下,它們相鄰的機率。請查閱 貝氏定理

  • P(A)是A的先驗機率或邊緣機率。之所以稱為”先驗”是因為它不考慮任何B方面的因素。
  • P(A|B)是已知B發生後A的條件機率,也由於得自B的取值而被稱作A的後驗機率。
  • P(B|A)是已知A發生後B的條件機率,也由於得自A的取值而被稱作B的後驗機率。
  • P(B)是B的先驗機率或邊緣機率,也作標准化常量(normalizing constant).
$$P(s) = P(w_{0}) \times P(w_{1}|w_{0}) \times ... \times P(w_{n-1}|w_{n-2})$$

上述為一個句子的機率,一個句子可以表示成一個序列單詞,利用連乘積將機率算出。當句子越常時,很容易發現機率陡降的速度相當快,就算是數個字詞,機率大約也是在 $10^{-3}$ 左右。因此這麼算下去,長句子的正確性就會大幅減少,但是在邏輯上,如果句子都是短短幾個單詞也是相當奇怪的,口語上也許是,文章判讀上就難說。至於要不要取 $\sqrt[n]{x}$ 值得思考。

$$\begin{cases} Count^{*}(w_{i}) = (Count(w_{i})+1) \times \frac{N_{Count(w_{i})+1}}{N_{Count(w_{i})}} & \text{ if } Count(w_{i}) < k \\ Count^{*}(w_{i}) = Count(w_{i}) & \text{ if } Count(w_{i}) \geq k \end{cases} \\ \text{unigram } N_{0} = 80000 $$

當我們去計算一個單詞的機率時,必須相對於其他單詞的出現機率,然而像介係詞、助詞等,出現次數是相對高出取多,必須取一個閥值,來忽略過高無用的機率,以免將其他的單詞的機率過低不均。

$$\begin{cases} Count^{*}(w_{i}, w_{i+1}) = (Count(w_{i}, w_{i+1})+1) \times \frac{N_{Count(w_{i}, w_{i+1})+1}}{N_{Count(w_{i}, w_{i+1})}} & \text{ if } Count(w_{i}, w_{i+1}) < k \\ Count^{*}(w_{i}, w_{i+1}) = Count(w_{i}, w_{i+1}) & \text{ if } Count(w_{i}, w_{i+1}) \geq k \end{cases} \\ \text{bigram } N_{0} = 80000 \times 80000$$

在計算相鄰兩個單詞的出現次數時,一樣會遇到這種情況。既然在計算次數上需要做 smoothing 的調整,在機率處理上也是一樣動作。

$$\begin{cases} P(w_{i}) = \frac{N_{1}}{N} & \text{ if } Count(w_{i}) = 0 \\ P(w_{i}) = \frac{Count^{*}(w_{i})}{N} & \text{ if } Count(w_{i}) < K \\ P(w_{i}) = \frac{Count(w_{i})}{N} & \text{ if } Count(w_{i}) \geq K \end{cases}$$ $$\begin{cases} P(w_{i}, w_{i+1}) = \frac{Count^{*}(w_{i}, w_{i+1})}{N} & \text{ if } Count(w_{i}, w_{i+1}) < K \\ P(w_{i}, w_{i+1}) = \frac{Count(w_{i}, w_{i+1})}{N} & \text{ if } Count(w_{i}, w_{i+1}) \geq K \end{cases}$$

在單詞出現次數很少時,就必須使用 smoothing,因為出現 1 次、2 次、3 次 … 的單詞次數,之間大小關係不保證嚴格遞增或遞減,

實作細節

  • 公式都已經給定,基本上麻煩就是在於資料紀錄而已,其他就照著流程跑。
  • 雖然沒有規定語言,以下代碼在 Dev-C++ 下編過,別問 VS 到底行不行。

原則上,讀檔案,建立模型可以在 1.4 秒內完成

1
2
3
4
5
6
processing dataset.txt ...
read file end. Start prepare language model ...
input a sentence in a line :
--------------------------------
Process exited after 1.493 seconds with return value 0

測試輸入

1
2
3
4
5
6
7
8
causes AIDS and is associated with AIDS cases primarily in West Africa
AIDS cases primarily in West Africa
AIDS cases primarily at West Africa
AIDS cases primarily AIDS West Africa
morris
West Africa
East Africa
Taiwan Africa

測式輸出

考量長句子的機率,採用 log 平均結果,輸出應該為負值。

1
2
3
4
5
6
7
8
-4.597715
-4.796396
-5.992288
-7.245960
-1.857392
-4.639120
-8.003706
-8.003706

原始版本,直接輸出 P(s),這裡採用科學記號表示法。

1
2
3
4
5
6
7
8
1.101764e-026
2.622182e-015
6.068425e-019
9.372080e-023
2.436068e-002
9.031667e-007
3.733396e-011
3.733396e-011

結語

有 STL library,代碼不用太長,跑得時間也不會太久。想到插手別學校的自然語言處理,玩了一下他們作業,把同學的代碼效率修得好一點,其實也不錯玩得,只是在公式計算上比較沒有,但是要求高效率的搜索結構,讀檔案進來後,依據什麼建表、該用什麼順序完成是很重要的。

切記,在寫這種程式時,發現跑的速度太久,一部分是因為使用太多的標準輸出,也就是用太多 printf()cout <<System.out.println() 之類的在進行流程監控。輸出的效率必須將檔案寫到螢幕顯示的 memory buffer,因此 context-switch 什麼,消耗時間太大,盡可能不要輸出,要不然就是按比例輸出,速度可以快個數百倍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <stdio.h>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <sstream>
#include <math.h>
#include <ctype.h>
using namespace std;
#define DEBUG
class Model {
public:
map<string, int> Count;
map<pair<string, string>, int> Count2;
map<int, int> Ni;
map<int, int> Ni2;
int totalCountWord, totalCount2Word;
static const int K;
static const int V;
string str2lower(string s) {
for (int i = 0; i < s.length(); i++)
s[i] = tolower(s[i]);
return s;
}
void prepare() {
totalCountWord = totalCount2Word = 0;
for (map<string, int>::iterator it = Count.begin();
it != Count.end(); it++) {
Ni[it->second]++;
totalCountWord += it->second;
//#ifdef DEBUG
// if (it->second > 1000)
// printf("Count(%s) = %d\n", it->first.c_str(), it->second);
//#endif
}
for (map<pair<string, string>, int>::iterator it = Count2.begin();
it != Count2.end(); it++) {
Ni2[it->second]++;
totalCount2Word += it->second;
}
int smooth = 0x3f3f3f3f;
for (map<int, int>::iterator it = Ni.begin();
it != Ni.end(); it++) {
// smooth = min(smooth, it->second);
// it->second = smooth;
//#ifdef DEBUG
// printf("N(%d) = %d\n", it->first, it->second);
// getchar();
//#endif
}
}
double getN(int i) { // N_{Count(w)}
if (i == 0) return 80000;
map<int, int>::iterator it = Ni.lower_bound(i), jt;
if (it == Ni.begin()) return it == Ni.end() ? 1 : it->second;
jt = it, jt--;
double sx = jt->first, sy = jt->second, ex = it->first, ey = it->second;
return sy + (ey - sy) / (ex - sx) * (i - sx);
}
double getN2(int i) { // N_{Count(w_{i}, w_{i+1})}
if (i == 0) return 80000.0 * 80000.0;
map<int, int>::iterator it = Ni2.lower_bound(i), jt;
if (it == Ni2.begin()) return it == Ni2.end() ? 1 : it->second;
jt = it, jt--;
double sx = jt->first, sy = jt->second, ex = it->first, ey = it->second;
return sy + (ey - sy) / (ex - sx) * (i - sx);
}
double getCountStar(const string &w) { // Count^{*}(w_{i})
int n = Count[w];
if (n < K) {
return (double) (n + 1) * (getN(n + 1) / getN(n));
} else {
return n;
}
}
double getCountStar2(const string &w1, const string &w2) { // Count^{*}(w_{i}, w_{i+1})
int n = Count2[make_pair(w1, w2)];
if (n < K) {
return (double) (n + 1) * (getN2(n + 1) / getN2(n));
} else {
return n;
}
}
double getPofW1(const string &w) { // P(w_{i}) = \frac{Count(w_{i})}{\sum_{j} Count(w_{j})}
map<string, int>::iterator it = Count.find(w);
if (it == Count.end() || it->second == 0) { // Count(w_{i}) = 0
double Nu0 = V - Count.size();
return (double) getN(1) / Nu0 / totalCountWord; // \frac{N_{1}}{N}
} else if (it->second < K) { // 0 < Count(w_{i}) < K
return (double) getCountStar(w) / totalCountWord; // \frac{Count^{*}(w_{i})}{N}
} else { // Count(w_{i}) \geq K
return (double) it->second / totalCountWord; // \frac{Count(w_{i})}{N}
}
}
double getPofW2(const string &w1, const string &w2) { // P(w_{i}, w_{i+1})
map< pair<string, string>, int>::iterator it = Count2.find(make_pair(w1, w2));
if (it == Count2.end() || it->second == 0) {
double Nb0 = (double) V * V - Count2.size();
return (double) getN2(1) / Nb0 / totalCount2Word;
} else if (it->second < K) { // Count(w_{i}, w_{i+1}) < K
return (double) getCountStar2(w1, w2) / totalCount2Word; // \frac{Count^{*}(w_{i}, w_{i+1})}{N}
} else { // Count(w_{i}, w_{i+1}) \geq K
return (double) it->second / totalCount2Word; // \frac{Count(w_{i}, w_{i+1})}{N}
}
}
void parseStmt(vector<string> &stmt) {
for (int i = 0; i < stmt.size(); i++) {
stmt[i] = str2lower(stmt[i]);
Count[stmt[i]]++;
if (i)
Count2[make_pair(stmt[i-1], stmt[i])]++;
}
}
double getPs(string in) {
stringstream sin(in);
vector<string> stmt;
string token;
while (sin >> token)
stmt.push_back(str2lower(token));
// P(s) = P(w_{0}) \times P(w_{1}|w_{0}) \times ... \times P(w_{n-1}|w_{n-2})
double p = 1;
if (stmt.size() > 0)
p = getPofW1(stmt[0]);
for (int i = 1; i < stmt.size(); i++ ) {
p *= getPofW2(stmt[i-1], stmt[i]) / getPofW1(stmt[i-1]);
// printf("%lf\n", getPofW2(stmt[i-1], stmt[i]) / getPofW1(stmt[i-1]));
// cout << stmt[i-1] << " " << stmt[i] << endl;
// printf("%lf\n", getPofW2(stmt[i-1], stmt[i]));
}
return p;
}
} tool;
const int Model::K = 10, Model::V = 80000;
int main() {
ifstream fin("dataset.txt");
// freopen("tmp.txt", "w+t", stdout);
string token, line;
vector<string> stmt;
puts("processing dataset.txt ...");
while (getline(fin, line)) {
stringstream sin(line);
stmt.clear();
while (sin >> token) {
stmt.push_back(token);
}
tool.parseStmt(stmt);
}
puts("read file end. Start prepare language model ...");
tool.prepare();
puts("input a sentence in a line :");
while (getline(cin, line)) {
printf("P*('%s') : %.10e\n", line.c_str(), tool.getPs(line));
}
return 0;
}
/*
causes AIDS and is associated with AIDS cases primarily in West Africa
AIDS cases primarily in West Africa
AIDS cases primarily at West Africa
AIDS cases primarily AIDS West Africa
morris
IL-2 is a gene .
IL-2 is an gene .
*/
Read More +

[通識] 文明的進程 Week 5

文明化的過程,有可能整個記憶封鎖在過去的盒子中。

前言

本周上課講述的內容為 痰盂 ,在 18 世紀時,這盆子可說是相當受到歡迎,當我們發現吐痰這事衛生上有所疑慮,找了一個盆子還裝,就跟尿壺類似。但是問別人痰盂是何物時,大概也沒幾個人見過。

為什麼經過了 2 個世紀,痰盂就不見了,應該說是不被需要, 吐痰 這件事從正常行為,到不需要吐痰,當然還是有人或在某個狀態下會吐痰 (生病),由於環境的改善,尤其是空氣汙染的關係,痰並沒有必要性。

談吐痰行為

早期到處可見吐痰,可說是隨地大小便的程度,吐痰在地上踏踏輾輾即可,中間開始注意到衛生,不管東方西方都曾出現過 痰盂 ,甚至在大大小小的照片中還一起入鏡呢,外觀上與一般花盆無異,只是裡面裝的東西不同罷了。

後來開始用法規、法款來制止人們隨地吐痰,從不吐在室內開始,也許允許往外吐是件很可笑的事情,但是在過度時期也算個進步,至少人們還知道吐痰這個行為需要被約束。到了二十世紀仍然會有使用罰款的方式來告誡人們,那為什麼現在根本沒有看過這些警告標語呢?「 請不要隨地吐痰

他制到自制:外部或他人而遵守戒律 → 內化到自我強制

談約束禮儀

任何一個爛事,找一個 powerful 的理由,也能昇華!

在一個民主平等的社會中,才能用衛生健康的理由來約束人們。如果在那種貧富不均,又有階級高低之分的社會,物質分配不均,光是活著就有困擾,遵守禮儀這件事情何止奢侈可說。

如果看看在傳統菜市場買賣的人,用呼喊的方式叫賣,那樣的行為舉止,在有限的資源下,你還說什麼禮儀嗎,能賣出去就好,下次還要搶攤位賣呢。

社會組織的方式將會影響心理生活的可塑性,根據國情不同、情操與行為的主旨不同,心理上要適應新的規則模式,反應上也會有所不同。基於什麼樣的條件,接受某些事情的難易度不同。 (文理組織差,相互學習對方領域的可塑性也會有差別)

談我們

美當我們成長,越來越會覺得小孩子很吵,那我們還能這麼吵嗎?兇不起來的人類?越來越退化了嗎?接受禮儀的約束,在何種環境下,才能拿回被約束的習慣。

「當我們不只遵守禮儀,也會開始要求別人遵守禮儀」這必須看看台灣最強的人肉搜索,不外乎一個人做錯事情,馬上就會被人肉出來,必且大眾強力苛責這個人的行為,可見我們多麼要求別人遵守禮儀。在某些條件下,例如家裡、年紀之差,容忍不禮貌的程度也會不同。

幾件趣事

結合民族自尊心推動宣傳,當我們厭惡、崇尚其他民族時,它們活生生的例子就會是很好的宣傳,例如:西方人多麼高雅、韓國人常在體育賽事作弊 … 等,約束力相當好。

在早期哪有什麼裸體抗議,大家都是赤裸裸地睡覺、洗澡,不赤裸睡覺必有身體上的缺陷,不想引人猜疑,那時都是安妥妥地赤裸。而現在卻不同,赤裸居然可以拿來做為抗議手段,用一個羞恥力來擊倒敵人!

在人來人往的地方生活,就會不由自主地意識到他人的存在,任何行為不管是否被他人看見,都會論及自己是否會 貶值 的行為,做了某件事情,我是否就貶值了呢?因此焦慮心情在城市中也常在人們身上發現。

成人與小孩的衝突有時只是世代的價值衝突,而非禮儀上的學習多寡,當沒有過去世代的記憶,沒有那些曾經被拋下的某些行為經驗,不知道不做的原因,為何不做?

為什麼常有人不碰別人用過的東西?人際關係的 獨立 疏離 ,總覺得人越來越不是人了,說是昆蟲也不為過,之後就各自獨立生存,最終進化呢。

沒有一個時代的狀態可以做為 絕對化標準

少在那邊自己為是,可以說自己不夠好,但是絕不能批評別人太差,看到別人用你不曾使用的行為模式活著,才是訝異敬佩的地方-「 原來還可以這麼活著!

用範例教育成人該做、不該做的事情,也就是說什麼都能說,何必忌諱任何一個汙穢的事情。

越要說明一個真理,請拋開羞恥心去描述它吧。

Read More +