--- title: '海大高培-Python By Liao-Hsiu-I' disqus: hackmd --- 海大高培-Python By Liao-Hsiu-I === [TOC] (9/19)(第一堂) --- ### 生成網路-影像風格轉換 ```python= from __future__ import absolute_import, division, print_function, unicode_literals import tensorflow as tf import IPython.display as display import matplotlib.pyplot as plt import matplotlib as mpl import numpy as np import PIL.Image import time import functools import cv2 mpl.rcParams['figure.figsize'] = (12,12) mpl.rcParams['axes.grid'] = False def tensor_to_image(tensor): numy_array = np.squeeze(np.array(tensor*255, dtype=np.uint8)) return numy_array def gram_matrix(input_tensor): result = tf.linalg.einsum('bijc,bijd->bcd', input_tensor, input_tensor) input_shape = tf.shape(input_tensor) num_locations = tf.cast(input_shape[1]*input_shape[2], tf.float32) return result/(num_locations) def train_step(obj, image): with tf.GradientTape() as tape: outputs = obj.extractor(image) loss = obj.loss(outputs)+obj.total_variation_weight*tf.image.total_variation(image) grad = tape.gradient(loss, image) obj.opt.apply_gradients([(grad, image)]) image.assign(tf.clip_by_value(image, clip_value_min=tf.constant(0.0), clip_value_max=tf.constant(1.0))) class style_transfer: def __init__(self,style_layers=None,content_layers=None): vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet') if style_layers is None: style_layers = ['block1_conv1','block2_conv1','block3_conv1', 'block4_conv1', 'block5_conv1'] if content_layers is None: content_layers = ['block5_conv2'] self.style_layers = style_layers.copy() self.content_layers=content_layers.copy() self.num_style_layers = len(self.style_layers) self.num_content_layers = len(self.content_layers) outputs = [vgg.get_layer(name).output for name in style_layers+content_layers] self.model = tf.keras.Model([vgg.input],outputs) self.model.trainable = False def loss(self,outputs): gram_outputs = [gram_matrix(o) for o in outputs[:self.num_style_layers]] style_loss = tf.add_n([tf.reduce_mean((out-tar)**2) for out,tar in zip(gram_outputs,self.style_target)]) style_loss *= self.style_weight / self.num_style_layers content_loss = tf.add_n([tf.reduce_mean((out-tar)**2) for out,tar in zip(outputs[self.num_style_layers:],self.content_target)]) content_loss *= self.content_weight / self.num_content_layers loss = style_loss + content_loss return loss def extractor(self,image): processed_input = tf.keras.applications.vgg19.preprocess_input(image*255.0) outputs = self.model(processed_input) return outputs def transfer(self,content_image,style_image,style_weight=1.0e-2,content_weight=1.0e4,total_variation_weight=30,epochs=10,step_per_epoch=100): self.content_weight = content_weight self.style_weight = style_weight self.total_variation_weight = total_variation_weight style_output = self.extractor(style_image) content_output = self.extractor(content_image) self.style_target = [gram_matrix(s) for s in style_output[:self.num_style_layers]] self.content_target = content_output[self.num_style_layers:] self.opt = tf.optimizers.Adam(learning_rate=0.02, beta_1=0.99, epsilon=1e-1) image = tf.Variable(content_image) for step in range(epochs): for _ in range(step_per_epoch): train_step(self, image) display.clear_output(wait=True) display.display(PIL.Image.fromarray(tensor_to_image(image))) print("Train step: {}".format(step+1)) return tensor_to_image(image) ``` ```python= #載入content image content_url = 'https://i1.wp.com/boo2k.com/wp-content/uploads/2018/08/IMG_3349-1.jpg?resize=860%2C573&ssl=1' content_image_file = tf.keras.utils.get_file('content.jpg',origin=content_url,cache_subdir='datasets') content_image = cv2.imread(content_image_file) content_image = tf.image.convert_image_dtype(content_image[:,:,::-1],tf.float32) content_image = tf.image.resize(content_image,(content_image.shape[0]//4,content_image.shape[1]//4)) #content_image = np.array(PIL.Image.open('tree.jpg')).astype('float32')/255.0 #載入style image style_url = 'https://tse2.mm.bing.net/th?id=OIP.1KA-xMf_qquuwP0mL22OSAHaF7&pid=Api&P=0&w=202&h=162' style_image_file = tf.keras.utils.get_file('style.jpg',origin=style_url,cache_subdir='datasets') style_image = cv2.imread(style_image_file) style_image = tf.image.convert_image_dtype(style_image[:,:,::-1],tf.float32) style_image = tf.image.resize(style_image,(style_image.shape[0]//4,style_image.shape[1]//4)) #style_image = np.array(PIL.Image.open('Vassily_Kandinsky,_1913_-_Composition_7.jpg')).astype('float32')/255.0 plt.figure(figsize=(12,6)) plt.subplot(1, 2, 1) plt.imshow(content_image) plt.title('Content Image') plt.axis(False) plt.subplot(1, 2, 2) plt.imshow(style_image) plt.title('Style Image') plt.axis(False) plt.show() ``` ```python= transfer = style_transfer() image = transfer.transfer(content_image[tf.newaxis,:],style_image[tf.newaxis,:],epochs=15) ``` ```python= plt.figure(figsize=(18,6)) plt.subplot(1, 3, 1) plt.imshow(content_image) plt.title('Content Image') plt.axis(False) plt.subplot(1, 3, 2) plt.imshow(style_image) plt.title('Style Image') plt.axis(False) plt.subplot(1, 3, 3) plt.imshow(image) cv2.imwrite('stylied_image.png',image[:,:,::-1]) plt.title('Stylized Image') plt.axis(False) plt.show() ``` (11/21) --- ### code 1 noPronoun #### 仙貝知識 ```python= len(test_sentence) # test_sentence 這個 list 的長度 for i in range(5): print(i) test_sentence[0] # test_sentence 裡面的第一個字串, 編號從 0 開始 result = change_text(test_sentence[0]) # 呼叫 change_text function 並且得到回傳值、儲存在 result 裡面 newtext = test_sentence[0] + "\t" + result # 將字串拼接在一起, 其中 "\t" 是 TAB 定位符號 print(newtext) newtext ``` #### 正文 function def_1 ```python= def change_text(sentence): sentence = sentence.replace('你', '汝') # 會把字串中的「你」都改成「汝」 sentence = sentence.replace('我', '吾') # 會把字串中的「我」都改成「吾」 sentence = sentence.replace('妳', '汝們') # 會把字串中的「妳」都改成「汝們」 sentence = sentence.replace('您', '偉大的人') # 會把字串中的「您」都改成「偉大的人」 sentence = sentence.replace('祢', '神') # 會把字串中的「祢」都改成「神」 sentence = sentence.replace('他', 'he') # 會把字串中的「他」都改成「he」 sentence = sentence.replace('她', 'she') # 會把字串中的「她」都改成「she」 sentence = sentence.replace('祂', '神神') # 會把字串中的「祂」都改成「神神」 sentence = sentence.replace('它', 'item') # 會把字串中的「牠」都改成「item」 sentence = sentence.replace('牠', 'cat') # 會把字串中的「牠」都改成「cat」 # 請在此處加上其他代名詞取代規則 (10分) return sentence ``` list_1 datas ```python= test_sentence = [ # 這是一個 list, 裡面都是字串 "你好", "你說你想要逃", "妳是我的眼", "我們不說你我他", "我你妳您祢他她祂它牠" ] ``` #### 執行 ```python= for i in range(len(test_sentence)): result = change_text(test_sentence[i]) print(test_sentence[i] + "\t" + result) while True: sentence = input('請輸入句子 (over 代表結束遊戲):') if sentence == 'over': break sentence = change_text(sentence) print(sentence) print('下回見') ``` ### code 2 myEliza.ipynb #### 仙貝知識 ```python= k = test_sentence[0].find("死") # 在「我覺得我生活一片黯淡」句子中找 "死" 的出現位置k k = test_sentence[3].find("死") # 在「那個死傢伙」句子中找 "死" 的出現位置k sampleText = "死傢伙" k = sampleText.find("死") k # 句子開頭位置從 0 開始 sentence = input("請輸入:") # 從鍵盤打字,可以指定前面的提示訊息sentence ``` ```python= k = 1 while True: # 無窮迴圈 if k > 5: break # 直到符合某條件就跳出迴圈 print(k) k += 1 # 這行是把 k 的值加 1 ``` #### 正文 function def_1 ```python= def create_response(sentence): if sentence.find("死") >= 0: return "生命很寶貴,來電1995讓我陪你聊聊" elif sentence.find("自殺")>=0: return "張老師在你身邊"# 若在此處加上其他回覆可加分 (10分) else: sentence = sentence.replace('你', '吾')# 為了把「你」「我」互換,請先在此把「你」改成「吾」 sentence = sentence.replace('我', '你')# 交換人稱 sentence = sentence.replace('吾', '我')# 再把「吾」改成「我」 (10分) if sentence[0:2] == '因為': sentence = sentence[2:] sentence = '為什麼說' + sentence return sentence ``` ```python= test_sentence = [ "我覺得我生活一片黯淡", "因為我另一半不愛我了", "他跑去跟別人約會了", "那個死傢伙", "你好像聽不太懂我講的話" ] ``` #### 執行 ```python= print('Eliza\t今天覺得怎麼樣??') for i in range(len(test_sentence)): print("You\t" + test_sentence[i]) result = create_response(test_sentence[i]) print("Eliza\t" + result) print("Eliza\t今天覺得怎麼樣??") while True: sentence = input("You\t") if sentence == "881~": break sentence = create_response(sentence) print("Eliza\t" + sentence) print("Eliza\t881~") ``` ### code 3 simpleChatbot #### 仙貝知識 ```python= #解釋上述程式各行意義,先解釋 dictionary 是可以由 key 找 value 值的做法 print(dialogue["早安"]) myKey = "你好嗎" print(dialogue[myKey]) # if key in dialogue 這可以查找 dialogue 是否有這個 key 出現 myKey = "你好嗎" # 有收錄 print("YES") if myKey in dialogue else print("NO") myKey = "你好嗎?" # 沒收錄 print("YES") if myKey in dialogue else print("NO") # random.randrange(n) 會回傳一個 0 ~ (n-1) 的亂數 for i in range(10): print(random.randrange(100)) k = random.randrange(len(random_response)) # 拿到一個亂數,值在 random_response 長度範圍內 print(k) # 每次執行,結果都會不一樣 random_response[k] ``` #### 正文 import ```python= import random # 加入可提供亂數的模組 random.seed() # 亂數產生器需要先初始化 ``` function def_1 ```python= def get_response(sentence): if sentence in dialogue: return dialogue[sentence] else: k = random.randrange(len(random_response)) return random_response[k] ``` list_1 datas ```python= dialogue = { # 這是一種 dictionary, 每組資料都是 key : value , 查詢 key 可拿到 value "早安": "早安", "午安": "午安", "你好嗎": "我很好,謝謝!",# 加上兩組以上的應答 (10分) "你好": "你好!", "再見": "再見~" } random_response = ['嗯嗯', '呵呵', 'OSO'] ``` list_2 datas ```python= test_sentence = [ "早安", "你好嗎", "最近好嗎", "什麼", "你好奇怪", "再見" ] ``` #### 執行 ```python= for i in range(len(test_sentence)): print("You\t" + test_sentence[i]) result = get_response(test_sentence[i]) print("Chatbot\t" + result) while True: sentence = input("You\t") result = get_response(sentence) print("Chatbot\t" + result) if sentence == '再見': break ``` ### code 4 voiceCommand #### 仙貝知識 ```python= #解釋上述程式各行意義; commandSet 是一個 list of dictionary print(commandSet[0]["pattern"]) print(commandSet[0]["command"]) # regular expression 常用來寫比對字串的句型,但其實不太適合用來處理自然語言, 太多變化且要有詞的概念 print(re.search("[說講]", "說說看")) # [AB] 表示 A B 出現其中一個 print(re.search("[說講]", "演講")) print(re.search("[說講]", "看看")) print(re.search("[說講]笑話", "說笑話")) print(re.search("[說講]笑話", "可以講笑話嗎")) print(re.search("[說講]笑話", "說個笑話來聽")) print(re.search("[說講].*笑話", "說個笑話來聽")) # .* 表示中間可夾任意長度文字 print(re.search("(打開|開).*門", "能幫我打開廚房的門嗎?")) # (A|B) 也是 A B 任出現一個,但可多個字 print(re.search("(打開|開).*門", "我要開房間門")) print(re.search("(打開|開).*門", "芝麻開門"))#開始專門訓練=>false ``` #### 正文 import ```python= import re ``` list_1 datas ```python= commandSet = [ # 這是一個 list of dictionary #每加一種新功能可加 5 分,最多加到 20 分 {"pattern" : "[說講].*定義", "command" : "tell the defination"}, {"pattern" : "[說講].*原因", "command" : "tell the reason"}, {"pattern" : "[說講].*我喜歡你", "command" : "I love you"}, {"pattern" : "[說講].*故事", "command" : "tell a story"}, {"pattern" : "[說講].*笑話", "command" : "tell a joke"}, {"pattern" : "聽.*音樂", "command" : "listen to music"}, {"pattern" : "打開.*電視", "command" : "turn on the TV"}, {"pattern" : "打開.*冷氣", "command" : "turn on the air conditioner"}, {"pattern" : "(打開|開).*門", "command" : "open the door"} ] unknownCommand = "我聽不懂您的指令" ``` list_2 datas ```python= test_sentence = [ "你會講笑話嗎?", "說個笑話來聽聽", "你覺得我是個笑話嗎?", "能幫我打開廚房的門嗎?", "我要開房間門", "打開客廳的冷氣好了", "你好像聽不太懂我講的話" ] ``` #### 執行 ```python= for i in range(len(test_sentence)): print(test_sentence[i]) noMatch = True for j in range(len(commandSet)): if re.search(commandSet[j]["pattern"], test_sentence[i]) is not None: print("執行動作:" + commandSet[j]["command"]) noMatch = False # 比對到指令就把 noMatch 改成 False break # 並且 break 跳出迴圈、不用再比後面的指令 if noMatch: print(unknownCommand) print("您好,要我做什麼事?") sentence = input() noMatch = True for i in range(len(commandSet)): if re.search(commandSet[i]["pattern"], sentence) is not None: print("執行動作:" + commandSet[i]["command"]) noMatch = False break if noMatch: print(unknownCommand) ``` ### code 5 mySiri import ```python= import re # 加入 regular expression 比對的功能 import random ``` function def_1 ```python= def tell_a_joke(sentence): jokes = [ "易經的媽媽叫什麼\n\n\n\n\n液晶螢幕", "小明吃麻婆豆腐,麻婆告他性騷擾", "死掉的腎臟,猜一本中國小說?\n\n\n\n\n答案:西遊記(台語:死腰子)" ] # https://w199584.pixnet.net/blog/post/16756643 print(jokes[0]) # 現在一直印出第一個笑話 print(jokes[random.randrange(len(jokes))] )# 若改成亂數選一則笑話印出,加 15 分 (可參考 simpleChotbot) ``` google_res def_1 ```python= def find_restaurant(sentence): print("找到的餐廳:") for i in range(len(restaurant)): if (sentence.find(restaurant[i]["type"]) >= 0): print("\t" + restaurant[i]["name"]) ``` google_res def_2 ```python= def find_rating(sentence): for i in range(len(restaurant)): if (sentence.find(restaurant[i]["name"]) >= 0): print(restaurant[i]["name"] + "評價" + str(restaurant[i]["rate"]) + "顆星") ``` google_res def_3 ```python= def find_buffet(sentence): print("自助區:") for i in range(len(restaurant)): if (sentence.find(restaurant[i]["buffet"]) >= 0): print("\t" + restaurant[i]["name"]) ``` function def_2 ```python= def phone_call(sentence): k = sentence.find('給') if k >= 0: print("現在要打電話給" + sentence[k+1:]) # 目前是印出對方的名字 # 模仿 restaurant[] 建立電話簿 phone_book 記錄人名、電話。 # 可以用上面找到的人名查出他的電話號碼。完成此功能加 15 分 ``` google_name def_1 ```python= def find_phone(sentence): #sentence=人名 print("人名:") for i in range(len(phone_book)): if (sentence.find(phone_book[i]["name"]) >= 0): print(phone_book[i]["name"] + "的電話是" + phone_book[i]["phone_num"]) ``` list_1 datas ```python= restaurant = [ {"name":"麥當當", "type":"速食店", "rate":3.5, "service":"free black tea"}, {"name":"大家牛排", "type":"牛排館", "rate":3.8, "service":"free milk"}, {"name":"超好吃", "type":"牛排館", "rate":4.7, "service":"free green tea"}, {"name":"肯爺爺", "type":"速食店", "rate":3.5, "service":"free cola"}, {"name":"貴貴世家", "type":"牛排館", "rate":3.2, "service":"free coffee"} ] # 若餐廳能新增其他欄位 (例如價位...) 並增加相對應的查詢功能 (和 find_restaurant() 一樣) 加 20 分 ``` list_2 datas ```python= phone_book = [ {"name":"BECKETT", "phone_num":"0934975931"}, {"name":"ROSEMARY", "phone_num":"0970954407"}, {"name":"MILBURN", "phone_num":"0914186333"}, {"name":"MERTON", "phone_num":"0915273181"}, ] ``` list_3 datas ```python= commandSet = [ # 這是一個 list of dictionary {"pattern" : "(打電話|撥號)給", "command" : phone_call}, {"pattern" : "[說講].*笑話", "command" : tell_a_joke}, {"pattern" : "幫我找(這)?(附近的)?", "command" : find_restaurant}, {"pattern" : ".*(的)?評價如何", "command" : find_rating} ] unknownCommand = "我聽不懂您的指令" ``` #### 執行 ```python= test_sentence = [ "你會講笑話嗎?", "說個笑話來聽聽", "打電話給林志玲", "撥號給老爸", "幫我找速食店", "幫我找這附近的牛排館", "大家牛排評價如何" ] for i in range(len(test_sentence)): print(test_sentence[i]) noMatch = True for j in range(len(commandSet)): if re.search(commandSet[j]["pattern"], test_sentence[i]) is not None: func = commandSet[j]["command"] func(test_sentence[i]) noMatch = False # 比對到指令就把 noMatch 改成 False break # 並且 break 跳出迴圈、不用再比後面的指令 if noMatch: print(unknownCommand) print("您好,要我做什麼事?") sentence = input() noMatch = True for i in range(len(commandSet)): if re.search(commandSet[i]["pattern"], sentence) is not None: func = commandSet[i]["command"] func(sentence) noMatch = False break if noMatch: print(unknownCommand) ``` ## (12/5) ### 語音指令介面_段詞 ```python= !pip install -U DistilTag ``` ```python= import DistilTag DistilTag.download() ``` ```python= from DistilTag import DistilTag tagger = DistilTag() # 這是一個可進行中文斷詞及詞性標記的系統 ``` ```python= import re # 加入 regular expression 比對的功能 unknownCommand = "\t回答:我聽不懂您的指令" ``` ```python= command_set_wseg = [ # 修改上回的指令集,考慮斷詞邊界 {"pattern" : "\\b[說講]\\b.*\\b笑話\\b", "command" : "tell a joke"}, {"pattern" : "\\b打開\\b.*\\b冷氣\\b", "command" : "turn on the air conditioner"}, {"pattern" : "\\b(打開|開)\\b.*\\b門\\b", "command" : "open the door"} ] test_sentence_raw = [ # 句子沒有斷詞 "你會講笑話嗎?", "這是演講聽到的笑話", "能幫我打開廚房的門嗎?", "我要開始專門訓練課程了", "打開客廳的冷氣好了", "你好像聽不太懂我講的話" ] for i in range(len(test_sentence_raw)): print("You: " + test_sentence_raw[i]) tagged = tagger.tag(test_sentence_raw[i])# 先對句子斷詞 sent_tagged = "" for j in tagged[0]: print(j) sent_tagged = sent_tagged + str(j[0]) +" " # 請在此處使用 tagger 將 test_sentence_raw[i] 斷詞、拼接成 sent_tagged # (20 分) print("\t" + sent_tagged) noMatch = True for j in range(len(command_set_wseg)): matchStr = re.search(command_set_wseg[j]["pattern"], sent_tagged) if matchStr is not None: print("\t符合字串:[" + matchStr.group() + "]\n\t執行動作:" + command_set_wseg[j]["command"]) noMatch = False # 比對到指令就把 noMatch 改成 False break # 並且 break 跳出迴圈、不用再比後面的指令 if noMatch: print(unknownCommand) ``` ```python= hw_sentence = [ "你會講笑話嗎?", "康橋的靈性全在一條河上;康河,我敢說,是全世界最秀麗的一條水。", "用一轉身離開,用一輩子去忘記。", "這一次的曲調卻是柔和之至,宛如一人輕輕歎息。", "「他喜歡你這般打扮做鬼臉,那還用說。你是他的大玩偶。」", "學院分配儀式是非常重要的,因為你在霍格華茲的時候,你的學院就像你的家一樣。" ] for i in range(len(hw_sentence)): print("You: " + hw_sentence[i]) tagged = tagger.tag(hw_sentence[i])# 先對句子斷詞 sent_tagged = "" for j in tagged[0]: print(j) print(j[0]) sent_tagged = sent_tagged + j[0] +" " # 請在此處使用 tagger 將 hw_sentence[i] 斷詞、拼接成 sent_tagged # (20 分) print("\t" + sent_tagged) # 對各個句子斷詞,將斷詞結果貼到 TronClass 測驗卷中 # 例如第一個句子會成為「你 會 講 笑話 嗎 ?」 ``` ### 搜尋拍賣文章 ```python= # 假設拍賣網站的文章都已斷好詞如下 saleDoc = [ ["英倫", "風", "羅馬", "布", "材質", "休閒", "長褲", "棉褲"], ["學院", "風", "劍", "領", "休閒", "西服", "英倫", "雅痞", "棉質", "針織", "外套", "韓", "版", "修身", "外套", "西裝", "韓劇", "都敏俊", "同", "款"], ["舒適", "休閒", "素面", "中性", "百", "搭", "休閒", "鞋", "5", "色"], ["防風", "外套", "防水", "透氣", "防曬", "輕薄", "騎士", "外套"], ["經典", "不", "敗", "夏季", "薄", "款", "牛仔", "襯衫", "輕薄", "外套", "微", "刷色", "深藍", "/", "淺藍"], ["小", "曼", "超", "愛", "款", "🎉", "特價", "🉐", "韓國", "打", "版", "一字", "涼", "拖鞋", "(", "二", "色", ")"], ["氣質", "穿", "搭", "台灣", "手工", "尖頭", "氣質", "繞", "踝", "平底鞋"], ["Vans", "專櫃", "代購", "經典", "款", "學生", "最愛", "帆布鞋"], ["人氣", "冠軍", "👑", "👑", "百", "搭", "單品", "❤", "不", "咬", "腳", "金屬", "簡約", "軟", "底", "平底鞋"], ["藤麻", "編織", "金屬", "皮革", "懶人", "鞋", "/", "平底鞋"], ] ``` ```python= query_str = "氣質 外套 鞋 牛仔" # 查詢字串 query = query_str.split(" ") # 依空白切出各查詢詞 query ``` ```python= doc_score = [] for i in range(len(saleDoc)): score = 0 for q in query: if q in saleDoc[i]: #多次出現仍+1 score = score + 1 if score > 0: t = [score, saleDoc[i]] #[分數,類型] doc_score.append(t) doc_score.sort(reverse = True) #按分數高低排列 doc_score ``` ```python= synset = [ #同義詞 ["舒適", "休閒"], ["氣質", "優雅", "經典", "雅痞"], ["拖鞋","平底鞋"], ["皮革","鞋"] ] def is_synonym(x, y): for sy in synset: if x in sy and y in sy and x != y: return True return False def has_synonym_in_doc(token, doc): for w in doc: if is_synonym(token, w): return True return False ``` ```python= doc_score = [] for i in range(len(saleDoc)): score = 0 for q in query: if q in saleDoc[i] or has_synonym_in_doc(q, saleDoc[i]): score = score + 1 if score > 0: t = [score, saleDoc[i]] doc_score.append(t) doc_score.sort(reverse = True) doc_score ```