高通台灣AI黑客松|競賽說明會
|

【Tutorial】運用KNN演算法進行室內定位 Part 2

   

作者:Ches拔(Sco Lin

在【Tutorial:運用KNN演算法進行室內定位(Part 1)】這篇文章中,以模擬數據做室內定位,獲得相當熱烈的回響,於是決定在這一篇實作Machine Learning,讓大家小試身手玩一玩^ ^ 鄉民都說要「有圖有證據」,這篇有圖code有數據,是燒燙燙掛保證。Maker也能玩轉AI,不是只有嘴上玩轉AI!在上一篇文章中,已嘗試過用文言文(見原作),於是這一篇決定嘗試再用另一格風格寫作!

醫生遞了一杯溫水給我,自己再拉了一張椅子坐在我的正對面。

「好了!保持心情平靜!星期日的晚上在醫院內沒什麼大餐可以請你,但這杯溫水會讓你舒服很多。我們來回想你這一週做了些什麼吧!」

「首先,你還記得除了登機以外,前幾天的事嗎?你還記不記得你在哪裡工作?家裡有幾個人?」醫生熟練的說出這些問題,但我的腦袋卻沒有辦法熟練的運轉。

「嗯…我想我是跟太太住在一起,我為一家專門投標政府專案的科技公司工作,印象中週一的時候,我有請假,因為陪太太去產檢。」

「很好,記得產檢時醫生說了些什麼嗎?』」

「因為太太一直睡不好,醫生建議可以吃一些含鎂的食物,例如芝麻糊或杏仁,其中好像還有提到便秘吧…我有點記不清楚了!」

「所以週一是請全天假在產檢?」

「不!下午是產檢,早上我幫一位大學同學代課。」

「那你還記得詳細的課程內容嗎?」

「我記得是在講『人工智慧』,因為有一位學生對其中的演算法很感興趣,所以幾乎都圍繞著某個主題。但說來奇怪,課程結束後,我的大學同學告訴我,發問的那一位不是他班上的學生,年紀也不像學生。他不反對旁聽,但這位讓我印象深刻。」

「說來聽聽。」醫生背靠著椅子,一雙修長的雙腿很自然的換了一個舒服的姿勢。

「由於公司先前做了一個有趣的室內定位演算法,為了這堂課我做了一個30×30的小型定位系統,圖大概是下面這個樣子,共54個點的2維定位系統。」

「嗯!很好!我大學時期的室友也做過這種研究,請繼續!」醫生馬上了解圖代表什麼,要求我用不怎麼靈光的腦袋繼續運轉解釋著。

「這是一個機器學習KNN的演算法,假設我們在這54個點是在地板上面,在天花板內有3個接收器,我從Google上找了一張圖用來說明是用紙箱做實驗。」

 

「透過機器學習,假設有一個人載著一只手環,在每1個點的位置上,找出這3個接收器的RSSI值及標註xy座標,也就是這種格式(-70 -60, -53, -4, 3)。-70代表接收器1的RSSI強度、-60為接收器2、-53代表接收器3、而-4, 3表示xy的交點。然後這54個點全部都用這種格示標註,這時候如果有人戴著手環走進來就可以判斷這個人在室內的哪個位置。」

「但這種方法很耗人力!」醫生面無表情的說。

「沒錯,單點標註的方式非常浪費時間,其實有比較聰明的方法。例如,你在家中喝杯茶,機器人幫你掃地加上拖地,順便連xy軸建模與家中平面圖都完成的方式。但在這裡為了教學,我決定一點一點這樣做,總共做了以下54筆的數據。」

單點標註出的54筆數據

(-70 -60, -53, -4, 3)

(-65, -60, -58, -3, 3)

(-65, -59, -60, -2, 3)

(-62, -67 -62, -1, 3)

(-68, -52, -67, 0, 3)

(-58, -50, -60, 1, 3)

(-65, -52, -66, 2, 3)

(-62, -54, -65, 3, 3)

(-67, -54, -57, 4, 3)

(-65 -64, -64, -4, 2)

(-64, -68, -61, -3, 2)

(-66, -72, -60, -2, 2)

(-70, -59, -64, -1, 2)

(-65, -53, -62, 0, 2)

(-60, -50, -72, 1, 2)

(-60, -51, -58, 2, 2)

(-68, 49, -62, 3, 2)

(-71, -49, -60, 4, 2)

(-65 -56, -56, -4, 1)

(-66, -60, -64, -3, 1)

(-64, -55, -61, -2, 1)

(-63, -54, -63, -1, 1)

(-65, -54, -64, 0, 1)

(-64, -52, -68, 1, 1)

(-67, -53, -65, 2, 1)

(-70, -50, -66, 3, 1)

(-71, -50, -60, 4, 1)

(-65 -56, -62, -4, 0)

(-61, -57, -63, -3, 0)

(-60, -55, -60, -2, 0)

(-59, -56, -63, -1, 0)

(-65, -54, -63, 0, 0)

(-64 -52, -63, 1, 0)

(-68, -51, -64, 2, 0)

(-65, -49, -65, 3, 0)

(-63, -55, -65, 4, 0)

(-68 -58, -60, -4, -1)

(-59, -60, -73, -3, -1)

(-55, -57, -59, -2, -1)

(-57, -55, -58, -1, -1)

(-56, -54, -62, 0, -1)

(-60 -51, -63, 1, -1)

(-70, -51, -65, 2, -1)

(-60, -50, -63, 3, -1)

(-64, -53, -65, 4, -1)

(-57 -63, -57, -4, -2)

(-61, -69, -55, -3, -2)

(-58, -59, -59, -2, -2)

(-59, -62, -66, -1, -2)

(-61, -60, -60, 0, -2)

(-57 -61, -59, 1, -2)

(-55, -63, -59, 2, -2)

(-59, -55, -59, 3, -2)

(-60, -57, -60, 4, -2)

 

「別小看這54筆數據,對無線電波的折射與繞射是有很大的影響。接下來把手環放在(2,0)的地方,測試接收器1~3的RSSI值是(-64, -55, -67),再假設輸入值是(-64, -55, -67, 0, 0),0代表我們現在不知道實際的xy是什麼,結果機器學習後,計算出來的數值為x =1.428571,y=0.428571,誤差實際用量尺差了3.5公分,這個Error有點高,但只是KNN。本來還想再往RNN與Deep Learning算下去的,但時間不太夠。」

「照你的做法,數據整理與無線接收器的擺放位置及精確度,是這個課程的要點。」醫生說。

「我想你的做法應該會是這樣……」眼前的女醫生,不只將邏輯畫了出來,更是把pseudo code也一併寫出來,感覺她比我還懂,在這5分鐘內,我都以不可置信的眼神看著她。

「忘了說,我輔修過類神經網路,跟著室友一起,我對科學也很感興趣。」醫生終於停筆,注意到找回我的記憶才是重點。

「沒關係!既然妳對這個很了解,多花2分鐘也無妨,有沒有電腦?」我對醫生說道。

醫生帶我去她的辦公室,我打開了自己的Github帳戶,在線上的python網站上貼上代碼:

代碼

from matplotlib import pyplot as plt

import numpy as np

import math

def Euclidean(vec1, vec2):

npvec1, npvec2 = np.array(vec1), np.array(vec2)

return math.sqrt(((npvec1-npvec2)**2).sum())

def Cosine(vec1, vec2):

npvec1, npvec2 = np.array(vec1), np.array(vec2)

return npvec1.dot(npvec2)/(math.sqrt((npvec1**2).sum()) * math.sqrt((npvec2**2).sum()))

def show_distance(exit_point, c):

o_dis = round(Euclidean(exit_point, c), 2)

return o_dis

def create_trainset():

trainset_tf = dict()

trainset_tf[u’an43V1, an43W1, an43X1, an43Y1, an43Z1′] = np.array([-70, -60, -53, -4, 3])

trainset_tf[u’an33V2, an33W2, an33X2, an33Y2, an33Z2′] = np.array([-65, -60, -58, -3, 3])

trainset_tf[u’an23V3, an23W3, an23X3, an23Y3, an23Z3′] = np.array([-65, -59, -60, -2, 3])

trainset_tf[u’an13V4, an13W4, an13X4, an13Y4, an13Z4′] = np.array([-62, -67, -62, -1, 3])

trainset_tf[u’a03V5, a03W5, a03X5, a03Y5, a03Z5′] = np.array([-68, -52, -67, 0, 3])

trainset_tf[u’bp13V6, bp13W6, bp13X6, bp13Y6, bp13Z6′] = np.array([-62, -67, -62, -1, 3])

trainset_tf[u’bp23V7, bp23W7, bp23X7, bp23Y7, bp23Z7′] = np.array([-62, -67, -62, -1, 3])

trainset_tf[u’bp33V8, bp33W8, bp33X8, bp33Y8, bp33Z8′] = np.array([-62, -67, -62, -1, 3])

trainset_tf[u’bp43V9, bp43W9, bp43X9, bp43Y9, bp43Z9′] = np.array([-62, -67, -62, -1, 3])

trainset_tf[u’an42V1, an42W1, an42X1, an42Y1, an42Z1′] = np.array([-65, -64, -64, -4, 2])

trainset_tf[u’an32V2, an32W2, an32X2, an32Y2, an32Z2′] = np.array([-64, -68, -61, -3, 2])

trainset_tf[u’an22V3, an22W3, an22X3, an22Y3, an22Z3′] = np.array([-66, -72, -60, -2, 2])

trainset_tf[u’an12V4, an12W4, an12X4, an12Y4, an12Z4′] = np.array([-70, -59, -64, -1, 2])

trainset_tf[u’a02V5, a02W5, a02X5, a02Y5, a02Z5′] = np.array([-65, -53, -62, 0, 2])

trainset_tf[u’bp12V6, bp12W6, bp12X6, bp12Y6, bp12Z6′] = np.array([-60, -50, -72, 1, 2])

trainset_tf[u’bp22V7, bp22W7, bp22X7, bp22Y7, bp22Z7′] = np.array([-60, -51, -58, 2, 2])

trainset_tf[u’bp32V8, bp32W8, bp32X8, bp32Y8, bp32Z8′] = np.array([-68, 49, -62, 3, 2])

trainset_tf[u’bp42V9, bp42W9, bp42X9, bp42Y9, bp42Z9′] = np.array([-71, -49, -60, 4, 2])

trainset_tf[u’an41V1, an41W1, an41X1, an41Y1, an41Z1′] = np.array([-65, -56, -56, -4, 1])

trainset_tf[u’an31V2, an31W2, an31X2, an31Y2, an31Z2′] = np.array([-66, -60, -64, -3, 1])

trainset_tf[u’an21V3, an21W3, an21X3, an21Y3, an21Z3′] = np.array([-64, -55, -61, -2, 1])

trainset_tf[u’an11V4, an11W4, an11X4, an11Y4, an11Z4′] = np.array([-63, -54, -63, -1, 1])

trainset_tf[u’a01V5, a01W5, a01X5, a01Y5, a01Z5′] = np.array([-65, -54, -64, 0, 1])

trainset_tf[u’bp11V6, bp11W6, bp11X6, bp11Y6, bp11Z6′] = np.array([-64, -52, -68, 1, 1])

trainset_tf[u’bp21V7, bp21W7, bp21X7, bp21Y7, bp21Z7′] = np.array([-67, -53, -65, 2, 1])

trainset_tf[u’bp31V8, bp31W8, bp31X8, bp31Y8, bp31Z8′] = np.array([-70, -50, -66, 3, 1])

trainset_tf[u’bp41V9, bp41W9, bp41X9, bp41Y9, bp41Z9′] = np.array([-71, -50, -60, 4, 1])

trainset_tf[u’a40V1, a40W1, a40X1, a40Y1, a40Z1′] = np.array([-65, -56, -62, -4, 0])

trainset_tf[u’a30V2, a30W2, a30X2, a30Y2, a30Z2′] = np.array([-61, -57, -63, -3, 0])

trainset_tf[u’a20V3, a20W3, a20X3, a20Y3, a20Z3′] = np.array([-60, -55, -60, -2, 0])

trainset_tf[u’a10V4, a10W4, a10X4, a10Y4, a10Z4′] = np.array([-59, -56, -63, -1, 0])

trainset_tf[u’a00V5, a00W5, a00X5, a00Y5, a00Z5′] = np.array([-65, -54, -63, 0, 0])

trainset_tf[u’b10V6, b10W6, b10X6, b10Y6, b10Z6′] = np.array([-64, -52, -63, 1, 0])

trainset_tf[u’b20V7, b20W7, b20X7, b20Y7, b20Z7′] = np.array([-68, -51, -64, 2, 0])

trainset_tf[u’b30V8, b30W8, b30X8, b30Y8, b30Z8′] = np.array([-65, -49, -65, 3, 0])

trainset_tf[u’b40V9, b40W9, b40X9, b40Y9, b40Z9′] = np.array([-63, -55, -65, 4, 0])

trainset_tf[u’an4n1V1, an4n1W1, an4n1X1, an4n1Y1, an4n1Z1′] = np.array([-68, -58, -60, -4, -1])

trainset_tf[u’an3n1V2, an3n1W2, an3n1X2, an3n1Y2, an3n1Z2′] = np.array([-59, -60, -73, -3, -1])

trainset_tf[u’an2n1V3, an2n1W3, an2n1X3, an2n1Y3, an2n1Z3′] = np.array([-55, -57, -59, -2, -1])

trainset_tf[u’an1n1V4, an1n1W4, an1n1X4, an1n1Y4, an1n1Z4′] = np.array([-57, -55, -58, -1, -1])

trainset_tf[u’a0n1V5, a0n1W5, a0n1X5, a0n1Y5, a0n1Z5′] = np.array([-56, -54, -62, 0, -1])

trainset_tf[u’bp1n1V6, bp1n1W6, bp1n1X6, bp1n1Y6, bp1n1Z6′] = np.array([-60, -51, -63, 1, -1])

trainset_tf[u’bp2n1V7, bp2n1W7, bp2n1X7, bp2n1Y7, bp2n1Z7′] = np.array([-70, -51, -65, 2, -1])

trainset_tf[u’bp3n1V8, bp3n1W8, bp3n1X8, bp3n1Y8, bp3n1Z8′] = np.array([-60, -50, -63, 3, -1])

trainset_tf[u’bp4n1V9, bp4n1W9, bp4n1X9, bp4n1Y9, bp4n1Z9′] = np.array([-64, -53, -65, 4, -1])

trainset_tf[u’an4n2V1, an4n2W1, an4n2X1, an4n2Y1, an4n2Z1′] = np.array([-57, -63, -57, -4, -2])

trainset_tf[u’an3n2V2, an3n2W2, an3n2X2, an3n2Y2, an3n2Z2′] = np.array([-61, -69, -55, -3, -2])

trainset_tf[u’an2n2V3, an2n2W3, an2n2X3, an2n2Y3, an2n2Z3′] = np.array([-58, -59, -59, -2, -2])

trainset_tf[u’an1n2V4, an1n2W4, an1n2X4, an1n2Y4, an1n2Z4′] = np.array([-59, -62, -66, -1, -2])

trainset_tf[u’a0n2V5, a0n2W5, a0n2X5, a0n2Y5, a0n1Z5′] = np.array([-61, -60, -60, 0, -2])

trainset_tf[u’bp1n2V6, bp1n2W6, bp1n2X5, bp1n2Y6, bp1n2Z6′] = np.array([-57, -61, -59, 1, -2])

trainset_tf[u’bp2n2V7, bp2n2W7, bp2n2X6, bp2n2Y7, bp2n2Z7′] = np.array([-55, -63, -59, 2, -2])

trainset_tf[u’bp3n2V8, bp3n2W8, bp3n2X7, bp3n2Y8, bp3n2Z8′] = np.array([-59, -55, -59, 3, -2])

trainset_tf[u’bp4n2V9, bp4n2W9, bp4n2X8, bp4n2Y9, bp4n2Z9′] = np.array([-60, -57, -60, 4, -2])

trainset_class = dict()

trainset_class[u’an43V1, an43W1, an43X1, an43Y1, an43Z1′] = ‘A’

trainset_class[u’an33V2, an33W2, an33X2, an33Y2, an33Z2′] = ‘A’

trainset_class[u’an23V3, an23W3, an23X3, an23Y3, an23Z3′] = ‘A’

trainset_class[u’an13V4, an13W4, an13X4, an13Y4, an13Z4′] = ‘A’

trainset_class[u’a03V5, a03W5, a03X5, a03Y5, a03Z5′] = ‘A’

trainset_class[u’bp13V6, bp13W6, bp13X6, bp13Y6, bp13Z6′] = ‘B’

trainset_class[u’bp23V7, bp23W7, bp23X7, bp23Y7, bp23Z7′] = ‘B’

trainset_class[u’bp33V8, bp33W8, bp33X8, bp33Y8, bp33Z8′] = ‘B’

trainset_class[u’bp43V9, bp43W9, bp43X9, bp43Y9, bp43Z9′] = ‘B’

trainset_class[u’an42V1, an42W1, an42X1, an42Y1, an42Z1′] = ‘A’

trainset_class[u’an32V2, an32W2, an33X2, an32Y2, an32Z2′] = ‘A’

trainset_class[u’an22V3, an22W3, an22X3, an22Y3, an22Z3′] = ‘A’

trainset_class[u’an12V4, an12W4, an12X4, an12Y4, an12Z4′] = ‘A’

trainset_class[u’a02V5, a03W5, a02X5, a02Y5, a02Z5′] = ‘A’

trainset_class[u’bp12V6, bp12W6, bp12X6, bp12Y6, bp12Z6′] = ‘B’

trainset_class[u’bp22V7, bp22W7, bp22X7, bp22Y7, bp22Z7′] = ‘B’

trainset_class[u’bp32V8, bp32W8, bp32X8, bp32Y8, bp32Z8′] = ‘B’

trainset_class[u’bp42V9, bp42W9, bp42X9, bp42Y9, bp42Z9′] = ‘B’

trainset_class[u’an41V1, an41W1, an41X1, an41Y1, an41Z1′] = ‘A’

trainset_class[u’an31V2, an31W2, an31X2, an31Y2, an31Z2′] = ‘A’

trainset_class[u’an21V3, an21W3, an21X3, an21Y3, an21Z3′] = ‘A’

trainset_class[u’an11V4, an11W4, an11X4, an11Y4, an11Z4′] = ‘A’

trainset_class[u’a01V5, a01W5, a01X5, a01Y5, a01Z5′] = ‘A’

trainset_class[u’bp11V6, bp11W6, bp11X6, bp11Y6, bp11Z6′] = ‘B’

trainset_class[u’bp21V7, bp21W7, bp21X7, bp21Y7, bp21Z7′] = ‘B’

trainset_class[u’bp31V8, bp31W8, bp31X8, bp31Y8, bp31Z8′] = ‘B’

trainset_class[u’bp41V9, bp41W9, bp41X9, bp41Y9, bp41Z9′] = ‘B’

trainset_class[u’a40V1, an40W1, an40X1, an40Y1, an40Z1′] = ‘A’

trainset_class[u’a30V2, an30W2, an30X2, an30Y2, an30Z2′] = ‘A’

trainset_class[u’a20V3, an20W3, an20X3, an20Y3, an20Z3′] = ‘A’

trainset_class[u’a10V4, an10W4, an10X4, an10Y4, an10Z4′] = ‘A’

trainset_class[u’a00V5, a00W5, a00X5, a00Y5, a00Z5′] = ‘A’

trainset_class[u’b10V6, b10W6, b10X6, b10Y6, b10Z6′] = ‘B’

trainset_class[u’b20V7, b20W7, b20X7, b20Y7, b20Z7′] = ‘B’

trainset_class[u’b30V8, b30W8, b30X8, b30Y8, b30Z8′] = ‘B’

trainset_class[u’b40V9, b40W9, b40X9, b40Y9, b40Z9′] = ‘B’

trainset_class[u’an4n1V1, an4n1W1, an4n1X1, an4n1Y1, an4n1Z1′] = ‘C’

trainset_class[u’an3n1V2, an3n1W2, an3n1X2, an3n1Y2, an3n1Z2′] = ‘C’

trainset_class[u’an2n1V3, an2n1W3, an2n1X3, an2n1Y3, an2n1Z3′] = ‘C’

trainset_class[u’an1n1V4, an1n1W4, an1n1X4, an1n1Y4, an1n1Z4′] = ‘C’

trainset_class[u’a0n1V5, a0n1W5, a0n1X5, a0n1Y5, a0n1Z5′] = ‘C’

trainset_class[u’bp1n1V6, bp1n1W6, bp1n1X6, bp1n1Y6, bp1n1Z6′] = ‘D’

trainset_class[u’bp2n1V7, bp2n1W7, bp2n1X7, bp2n1Y7, bp2n1Z7′] = ‘D’

trainset_class[u’bp3n1V8, bp3n1W8, bp3n1X8, bp3n1Y8, bp3n1Z8′] = ‘D’

trainset_class[u’bp4n1V9, bp4n1W9, bp4n1X9, bp4n1Y9, bp4n1Z9′] = ‘D’

trainset_class[u’an4n2V1, an4n2W1, an4n2X1, an4n2Y1, an4n2Z1′] = ‘C’

trainset_class[u’an3n2V2, an3n2W2, an3n2X2, an3n2Y2, an3n2Z2′] = ‘C’

trainset_class[u’an2n2V3, an2n2W3, an2n2X3, an2n2Y3, an2n2Z3′] = ‘C’

trainset_class[u’an1n2V4, an1n2W4, an1n2X4, an1n2Y4, an1n2Z4′] = ‘C’

trainset_class[u’a0n2V5, a0n2W5, a0n2X5, a0n2Y5, a0n2Z5′] = ‘C’

trainset_class[u’bp1n2V6, bp1n2W6, bp1n2X6, bp1n2Y6, bp1n2Z6′] = ‘D’

trainset_class[u’bp2n2V7, bp2n2W7, bp2n2X7, bp2n2Y7, bp2n2Z7′] = ‘D’

trainset_class[u’bp3n2V8, bp3n2W8, bp3n2X8, bp3n2Y8, bp3n2Z8′] = ‘D’

trainset_class[u’bp4n2V9, bp4n2W9, bp4n2X9, bp4n2Y9, bp4n2Z9′] = ‘D’

return trainset_tf, trainset_class

def knn_classify(input_tf, trainset_tf, trainset_class, k):

xy = np.array([0, 0])

tf_distance = dict()

print ‘(1) 計算向量距離’

for place in trainset_tf.keys():

tf_distance[place] = Euclidean(trainset_tf.get(place), input_tf)

print ‘\tTF(%s) = %f’ % (place, tf_distance.get(place))

class_count = dict()

print ‘(2) 取K個最近鄰居的分類, k = %d’ % k

for i, place in enumerate(sorted(tf_distance, key=tf_distance.get, reverse=False)):

current_class = trainset_class.get(place)

print ‘\tTF(%s) = %f, class = %s’ % (place, tf_distance.get(place), current_class)

class_count[current_class] = class_count.get(current_class, 0) + 1

xy = [(xy[0] + trainset_tf[place][3]),(xy[1] + trainset_tf[place][4])]

#print(trainset_tf[place])

if (i + 1) >= k:

break

print ‘(3) K個最近鄰居平均後得到x與y交點’

finalx=float(xy[0])/k

finaly=float(xy[1])/k

print ‘\tx = %f’ % finalx, ‘, y = %f’% finaly

print ‘(4) K個最近鄰居分類出現頻率最高的分類當作最後分類’

input_class = ”

for i, c in enumerate(sorted(class_count, key=class_count.get, reverse=True)): #不用reverse會以數值大的作區分,但我們是要挑小的

if i == 0:

input_class = c

print ‘\t%s, %d’ % (c, class_count.get(c))

print ‘(5) 分類結果 = %s’ % input_class

input_tf = np.array([-64, -55, -67, 0, 0]) #2,0

trainset_tf, trainset_class = create_trainset()

knn_classify(input_tf, trainset_tf, trainset_class, k=7)

結果如下:

「有意思!我看電腦在跑結果的時候花了快半秒時間,這是為什麼呢?」醫生說。

「如果我們用GPU運算也許會快很多,再來是這個代碼沒有最佳化,還需要修改。」

「看來你上週的記憶相當清晰。」醫生笑著說。

「可…我還沒說到那位令人印像深刻的學生…」這時辦公室外頭傳來快走的腳步聲,伴隨而來是2個男子的對話。

「他不見了!」其中一個臉色陰沈的男子說。腳步聲離我們愈來愈近,接著門把被轉了一下。

「現在是什麼情況!我覺得這些人是來找你的!你的公司主要是在做什麼?」醫生皺著眉頭說。

「我們公司做的事業很複雜,科技、家電、金融都有含括。畢竟是跨國企業,哪天賣起石油或挖礦都不覺得奇怪。」辦公室的門把突然又被轉動,伴隨來的是急促的敲門聲,看來對方很急著想打開這道門。

「快躲起來!」醫生要我站在辦公桌後面的窗戶外頭。

「什麼事嗎?」醫生開了門,對門外的人問道。

「您好,我是警察,請問您有碰到什麼奇怪的人嗎?」

「有!就是你!這麼晚了,醫院不會讓號稱是警察的人來查房,況且你也沒出示你的證件。」醫生不客氣的說。

「非常抱歉打擾,我們今天在看管一位危險人物,看來他不見了。」

「那你們最好馬上把他找出來,不要為我們醫院添麻煩。」醫生回覆。

「當然!如果您看到什麼奇怪的人,也麻煩跟我說一聲。」警察語畢,醫生隨即關上門,小聲的要我從寒冷的窗邊進來。

「看樣子你變成危險人物了,但依我看來,剛才來的那位比較危險,穿著全身黑,十字項鍊被拿在他燒傷的手,指甲縫也是黑的,完全不像是警察。」醫生簡單描述了剛才的對話。

「十字項鍊?燒傷的手?指甲縫?我剛才有提到那位印像深刻的學生嗎?」作為一個經驗豐富的醫師,醫生知道,她眼前這位病人有麻煩了。

不平靜的夜裡,消防車穿梭在高級住宅的巷弄裡,Christy與Carl早已入睡,Craig大約在凌晨3點上床。

7點,院長忙著早餐之後的工作,催促三位小朋友趕緊上課,但Craig還在被窩裡說著今天不想去學校。

Christy與Carl先坐車離開後,院長用極為耐心的口吻與被窩裡的Craig說話,直到Craig探出了身子,院長才發現Craig被燙傷的手掌…..

(本文同步發表於作者部落格 — 物聯網學習筆記文章連結;責任編輯:廖庭儀。)

(編按:本文原作為小說寫作風格,風格特殊,有興趣者不妨連回原作拜讀~)

Ches拔(Sco Lin)

訂閱MakerPRO知識充電報

與40000位開發者一同掌握科技創新的技術資訊!

Author: Ches拔(Sco Lin)

兩個男孩的爸爸、下班變身孩子王、衝浪閱讀與coding、PM擔當RD魂。

Share This Post On
468 ad

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *