# Python 10/17-11/14筆記整理 ___ ## 10/17運用Python進行科學計算 ### 1.本利和 本利是指在投資或貸款中所產生的利息,它是基於原始本金和利率的產物。計算本利的公式如下: $$ I = P \times r \times t $$ 其中: - \( I \) 代表本利(總利息), - \( P \) 代表原始本金, - \( r \) 代表利率(以小數形式表示,例如5%轉換為0.05), - \( t \) 代表時間(以年為單位)。 如果你想要計算總金額(本金加上本利),則公式如下: $$ A = P + I $$ 其中: - \( A \) 代表總金額。 ### 2.四捨五入VS沒有四捨五入的本利和 ```python= # 輸入資訊 P = 1000 # 假設本金為1000元 r = 0.03 # 年利率為3% n = 365 # 每天複利一次 t = 1 # 1年 # 計算每日利息 daily_interest = P * (r/n) # 計算本利和 A = P for _ in range(n*t): A += daily_interest A = round(A) # 每天結束後四捨五入到整數位 # 輸出結果 print("一年後的本利和為:", A) ``` :::success 一年後的本利和為: 1000 ::: ```python= import matplotlib.pyplot as plt # 設定參數 n = 365 # 複利次數(每年365次) t = 10 # 年數 # 計算每個本金 P 對應的差異 P_values = list(range(1000, 100001, 1000)) differences = [] for P in P_values: # 初始化有和無四捨五入的本利計算結果 A_with_rounding = P A_without_rounding = P # 進行複利計算 for _ in range(n * t): # 有四捨五入的計算 daily_interest = A_with_rounding * (r/n) A_with_rounding += daily_interest A_with_rounding = round(A_with_rounding) # 無四捨五入的計算 daily_interest_without_rounding = A_without_rounding * (r/n) A_without_rounding += daily_interest_without_rounding # 計算有和無四捨五入的差異 difference = A_with_rounding - A_without_rounding differences.append(difference) # 繪製圖表 plt.figure(figsize=(10, 6)) plt.plot(P_values, differences) plt.xlabel("Principal") plt.ylabel("Difference between Rounded and Unrounded Compound Interests") plt.title("Impact of Principal (P) on Differences") plt.grid(True) plt.show() ``` ![download](https://hackmd.io/_uploads/SJIJJQ9Ep.png) :::success 有四捨五入的本利和為: 1000 無四捨五入的本利和為: 1030.45326360051 有四捨五入與無四捨五入的差異為: -30.4532636005099 ::: ### 3.人口成長模型 ```python= import numpy as np import matplotlib.pyplot as plt # 定義參數 r = 0.1 # 增長率 M = 500 # 環境容量 u0 = 10 # 初始人口大小 num_steps = 100 # 模擬的時間步數 # 初始化數據 u_values = [u0] time_values = [0] # 進行數值模擬 for t in range(1, num_steps + 1): u_t = u_values[-1] # 使用 Logistic 模型的差分方程進行數值模擬 u_next = u_t + r * u_t * (1 - u_t/M) # 更新數據 u_values.append(u_next) time_values.append(t) # 繪製人口變化圖 plt.plot(time_values, u_values) plt.xlabel('時間') plt.ylabel('人口數') plt.title('Logistic 模型') plt.grid(True) plt.show() ``` ![download](https://hackmd.io/_uploads/SyPKLjdVa.png) ```python= ``` ## 10/24運用Python進行網路爬蟲 爬蟲的基本步驟: 發送請求: 使用程式代碼發送 HTTP 請求到目標網站的伺服器,獲取網頁內容。 解析 HTML: 使用解析庫(例如 BeautifulSoup 或 lxml)解析獲得的 HTML 內容,找到目標數據的標籤和屬性。 提取數據: 根據解析結果,提取出需要的數據,可以是文字、圖片、連結等。 存儲數據: 將提取的數據存儲在本地文件或數據庫中,以便後續分析或使用。 ### 1.抓成大故事觀點下面的內容 ```python= import requests from bs4 import BeautifulSoup # 指定目標網頁的URL url = 'https://www.ncku.edu.tw/' # 發送HTTP請求,獲取網頁內容 response = requests.get(url) # 檢查是否成功獲取網頁內容 if response.status_code == 200: # 使用Beautiful Soup解析網頁內容 soup = BeautifulSoup(response.text, 'html.parser') # 查找包含 "故事 觀點" 文字的元素。這是第一層,要注意從網頁檢查時,藍色的 elements_1 = soup.find_all('div', class_='mouter') # 打印找到的元素內容 k = 1 for element in elements_1: print(f"=== 第 {k} 個元素 ===") k = k + 1 # 在第一層元素中,查找包含 "d-item v-it col-sm-3" 類別的子元素 elements_2 = element.find_all('div', class_='d-item v-it col-sm-3') # 打印第二層元素的文本內容 for e in elements_2: print(e.text.strip()) else: print('無法獲取網頁內容') ``` :::success 【92 校慶】2023「永續之島策略設計策略系列論壇」 以永續前瞻為起點 回饋母校共好台灣 【92 校慶】2023 成材產業論壇 關心人類生存大環境 聚焦綠能科技與新經濟 【92 校慶】第三屆成電論壇 重量級校友、系友探討生成式 AI 發展趨勢 建築學系 45 級 黃南淵 : 如果不能看清楚眼前美麗的玫瑰,又如何期待明年春天的來臨|成大 112 傑出校友 ::: ### 2.抓獎學金資料 ```python= import requests from bs4 import BeautifulSoup def download_file(url, destination_filename): # 發送 HTTP 請求獲取文件 response = requests.get(url) response.raise_for_status() # 如果是 HTTP 錯誤,則拋出異常 with open(destination_filename, 'wb') as f: f.write(response.content) print(f"File saved to {destination_filename}") # 輸入網址 response = requests.get('https://assistance-osa.ncku.edu.tw/p/403-1051-699.php?Lang=zh-tw') # 解析成 HTML 語言 soup = BeautifulSoup(response.content, "html.parser") # 找到對應的 tag,find_all 之後要用一個 for-loop 把找到的一個一個列出來 mtitle = soup.find_all("section", class_="mb") for m in mtitle: # 再往下找對應的 title scholarship = m.find_all("div", class_="mtitle") for s in scholarship: # 找到 a 標籤,取得文字和連結 u = s.find('a') print(f"Title: {u.text.strip()}") # 找到 i 標籤,取得文字(日期等相關資訊) d = s.find('i') print(f"Date: {d.text.strip()}") # 打印連結 print(f"URL: {u['href']}") # 透過連結發送 HTTP 請求獲取子網頁內容 response2 = requests.get(u["href"]) soup2 = BeautifulSoup(response2.content, "html.parser") # 找到包含附件的區塊 attach = soup2.find('ul', class_='mptattach') # 找到附件的 a 標籤,取得文字和連結 file = attach.find('a') print(f"Attachment: {file.text.strip()}") print(f"Attachment URL: {file['href']}") # 下載文件 download_file("https://assistance-osa.ncku.edu.tw/"+file["href"], u.text.strip() + ".pdf") ``` :::success 112上漢翔航空工業股份有限公司-獎助碩博士獎學金 2023-11-20 https://assistance-osa.ncku.edu.tw/p/406-1051-260862,r699.php?Lang=zh-tw a15103-130.doc-.pdf /app/index.php?Action=downloadfile&file=WVhSMFlXTm9Mekk1TDNCMFlWOHhORGMxTmpOZk5UUTBNRFV6TUY4ME16QXpOeTV3WkdZPQ==&fname=B154RPOKIC44TXMPA404USWT34B4OOHC14B040YSA105DCTSKPZWLOUW14OK50XXYWPOHD0520A0TX24YWSWJGICQOICNORLUTJDA52114NO1111 File saved to 112上漢翔航空工業股份有限公司-獎助碩博士獎學金.pdf 112上財團法人嘉義西區扶輪社文教基金會-獎學金 2023-11-13 https://assistance-osa.ncku.edu.tw/p/406-1051-260547,r699.php?Lang=zh-tw a3491-407申請表格.odt /app/index.php?Action=downloadfile&file=WVhSMFlXTm9MelV2Y0hSaFh6RTBOelF4TjE4NU56RTNOVFV3WHpVNU1URTBMbTlrZEE9PQ==&fname=B154RPOKICWWVXMPA4TWJGWTVWB4GGIC14FGHGYSVXQLPO40NKB424B4WS10B4SSYW5400HHDG04EGHC34XSTSA1KL3410GCTXVXA4CC34A401OOOOA4XXWXROPOSSOO File saved to 112上財團法人嘉義西區扶輪社文教基金會-獎學金.pdf 國立成功大學永豐商業銀行傑出人才獎助學金 2023-11-13 https://assistance-osa.ncku.edu.tw/p/406-1051-260546,r699.php?Lang=zh-tw ::: 這個程式主要爬取了指定網頁中的相關資訊,包括獎學金標題、日期、連結和附件,然後進行文件下載。 ## 10/31運用Python進行圖像處理 :::info 用於下載兩張圖片,然後將它們水平合併成一張新的圖片。 1.download_image(url): 這個函數使用 requests 庫向指定的 URL 發送 HTTP 請求,然後使用 PIL 库的 Image.open 方法打開圖片。該函數返回打開的圖片對象。 2.concatenate_images(image1, image2): 這個函數接受兩個圖片對象,計算它們的合併寬度和高度,然後創建一個新的圖片對象(new_image)。接著,它使用 paste 方法將第一張圖片粘貼到新圖片的左側,將第二張圖片粘貼到右側。最終,它返回合併後的圖片對象。 3.指定兩個圖片的 URL,然後使用上述函數將它們合併成一張新的圖片。合併的過程是將第一張圖片的左側和右側分別粘貼上第二張圖片,形成一張寬度是兩張圖片寬度總和,高度是兩張圖片高度的最大值的新圖片。 4.顯示合併後的圖片:使用 matplotlib 的 imshow 方法顯示合併後的圖片,並且設置 plt.axis('off') 以隱藏座標軸。 5.儲存合併後的圖片:使用 save 方法將合併後的圖片保存到本地文件系統中。 ::: ### 1.拼接三張圖 ```python= import requests from PIL import Image from io import BytesIO import matplotlib.pyplot as plt def download_image(url): # 發送 HTTP 請求獲取圖片 response = requests.get(url) # 使用 PIL 库打開圖片 image = Image.open(BytesIO(response.content)) return image def concatenate_images(image1, image2): # 計算合併後的圖片寬度和高度 total_width = image1.width + image2.width max_height = max(image1.height, image2.height) # 創建一個新的圖片,大小為合併後的寬度和高度 new_image = Image.new('RGB', (total_width, max_height)) # 將第一張圖片粘貼到新圖片的左側 new_image.paste(image1, (0, 0)) # 將第二張圖片粘貼到新圖片的右側 new_image.paste(image2, (image1.width, 0)) return new_image # 替換成你的圖片網址 image_url1 = download_image("https://web.ncku.edu.tw/var/file/0/1000/img/DSC01181ok.jpg") image_url2 = download_image("https://web.ncku.edu.tw/var/file/0/1000/img/418380686.jpg") # 連接三張圖片 result_image = concatenate_images(image_url1, image_url2) result_image = concatenate_images(result_image, image_url1) # 顯示合併後的圖片 plt.imshow(result_image) plt.axis('off') # 不顯示座標軸 plt.show() # 儲存合併後的圖片 result_image.save("concatenated_image.jpg") ``` ![download](https://hackmd.io/_uploads/HyQi83OV6.png) ### 2.拼接圖片及文字 ```python= import requests from PIL import Image, ImageDraw, ImageFont from io import BytesIO import matplotlib.pyplot as plt def download_image(url): # 發送 HTTP 請求獲取圖片 response = requests.get(url) # 使用 PIL 库打開圖片 image = Image.open(BytesIO(response.content)) return image def draw_multiline_text(draw, text, position, font, max_width): lines = text.split('\n') y = position[1] for line in lines: # 使用 textbbox 獲取文字的尺寸 text_bbox = draw.textbbox((0, 0), line, font=font) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] # 計算文字位置 x = (max_width - text_width) / 2 + position[0] draw.text((x, y), line, font=font, fill="white") y += text_height def create_image_with_text(image_url, text): # 下載並獲取左邊的圖片 left_image = download_image(image_url) # 創建一個相同大小的黑色背景圖片 right_image = Image.new('RGB', left_image.size, color='black') # 在黑色背景圖片上添加文字 draw = ImageDraw.Draw(right_image) font_size = int(min(right_image.size) / 10) # 根據圖片大小調整字體大小 font = ImageFont.truetype("ThePeakFontBeta_V0_101.ttf", font_size) # 使用下載的字體 # 計算文字位置 max_width = right_image.width * 0.8 x = (right_image.width - max_width) / 2 y = (right_image.height - draw.textbbox((0, 0), text, font=font)[3]) / 2 draw_multiline_text(draw, text, (x, y), font, max_width) # 將左邊和右邊的圖片拼接 total_width = left_image.width + right_image.width new_image = Image.new('RGB', (total_width, left_image.height)) new_image.paste(left_image, (0, 0)) new_image.paste(right_image, (left_image.width, 0)) return new_image # 替換成你的圖片網址 image_url = "https://web.ncku.edu.tw/var/file/0/1000/img/DSC01181ok.jpg" # 輸入你想在右邊圖片中顯示的多行文字 text = "成大職治系實在好棒棒!\n成大職治系實在好棒棒!\n成大職治系實在好棒棒!" result_image = create_image_with_text(image_url, text) # 顯示合併後的圖片 plt.imshow(result_image) plt.axis('off') # 不顯示座標軸 plt.show() # 儲存合併後的圖片 result_image.save("image_with_multiline_text.jpg") ``` ![download](https://hackmd.io/_uploads/SkFbwnuNT.png) ### 3.拼接一張灰色調圖片 ```python= # 首先創建一個 ImageEnhance.Color 對象,然後使用 enhance 方法來調整圖片的顏色饱和度。增强後的圖片與原始圖片使用先前定義的 concatenate_images 函式進行左右合併,最後使用 matplotlib.pyplot 顯示合併後的圖片 # 创建一个颜色增强器对象 color_enhancer = ImageEnhance.Color(image) # 调整颜色饱和度(1.0 表示原始饱和度,小于 1.0 减弱饱和度,大于 1.0 增强饱和度) enhanced_image = color_enhancer.enhance(0.1) # 增强颜色饱和度 # 將原始圖片和增強後的圖片進行左右合併 combined_image = concatenate_images(image, enhanced_image) # 顯示合併後的圖片 plt.imshow(combined_image) plt.axis('off') # 不顯示座標軸 plt.show() ``` ![download](https://hackmd.io/_uploads/rynZt3OE6.png) ### 4.拼接一張模糊圖片 ```python= # 首先導入 ImageFilter 模組,然後使用 GaussianBlur 濾鏡對原始圖片進行模糊處理。接著,將原始圖片和模糊處理後的圖片使用先前定義的 concatenate_images 函式進行左右合併,最後使用 matplotlib.pyplot 顯示合併後的圖片 # 使用模糊滤镜进行模糊处理 blurred_image = image.filter(ImageFilter.GaussianBlur(radius=100)) # 將原始圖片和模糊處理後的圖片進行左右合併 combined_image = concatenate_images(image, blurred_image) # 顯示合併後的圖片 plt.imshow(combined_image) plt.axis('off') # 不顯示座標軸 plt.show() ``` ![download](https://hackmd.io/_uploads/ryDdF2_VT.png) ### 5.拼接一張負片 ```python= # 創建一個與原始圖片大小相同的空白圖片,然後遍歷原始圖片的每個像素,將RGB值取反後放入新的圖片中。最後,將原始圖片和取反處理後的圖片進行左右合併 # 获取图片的宽度和高度 width, height = image.size # 创建一个新的空白图片,与原始图片大小相同 negative_image = Image.new("RGB", (width, height)) # 遍历每个像素并取反RGB值 for x in range(width): for y in range(height): pixel = image.getpixel((x, y)) # 得到像素的值 tuple (R,G,B) inverted_pixel = tuple(255 - value for value in pixel) # 使用 for 循环生成 tuple 中的每个值,取反 RGB 值 negative_image.putpixel((x, y), inverted_pixel) # 把像素的(RGB)放回圖片中 # 將原始圖片和取反處理後的圖片進行左右合併 combined_image = concatenate_images(image, negative_image) # 顯示合併後的圖片 plt.imshow(combined_image) plt.axis('off') # 不顯示座標軸 plt.show() ``` ![download](https://hackmd.io/_uploads/ByCOY2ON6.png) ## 11/7運用Python進行遊戲設計 ### 1.井字遊戲 ```python= def 印出井字盤(井字盤): """ 印出井字遊戲的遊戲盤。 Parameters: - 井字盤 (list): 存放井字遊戲狀態的列表 """ print(井字盤[0] + '|' + 井字盤[1] + '|' + 井字盤[2]) print('-+-+-') print(井字盤[3] + '|' + 井字盤[4] + '|' + 井字盤[5]) print('-+-+-') print(井字盤[6] + '|' + 井字盤[7] + '|' + 井字盤[8]) def 檢查贏家(井字盤, 符號): """ 檢查是否有玩家贏得遊戲。 Parameters: - 井字盤 (list): 存放井字遊戲狀態的列表 - 符號 (str): 玩家的符號,'X' 或 'O' Returns: - bool: 若玩家贏得遊戲則返回 True,否則返回 False """ 贏的組合 = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], # 水平 [0, 3, 6], [1, 4, 7], [2, 5, 8], # 垂直 [0, 4, 8], [2, 4, 6] # 對角線 ] for 組合 in 贏的組合: if 井字盤[組合[0]] == 井字盤[組合[1]] == 井字盤[組合[2]] == 符號: return True return False def 主程式(): """ 井字遊戲的主程式。 """ 井字盤 = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] 玩家 = 'X' 輸贏平局 = None while True: 印出井字盤(井字盤) 輸入位置 = input(f'請玩家 {玩家} 輸入位置(1-9):') if 輸入位置.isdigit() and 1 <= int(輸入位置) <= 9: 輸入位置 = int(輸入位置) - 1 if 井字盤[輸入位置] == 'X' or 井字盤[輸入位置] == 'O': print('該位置已被佔據,請重新輸入。') else: 井字盤[輸入位置] = 玩家 if 檢查贏家(井字盤, 玩家): 印出井字盤(井字盤) print(f'恭喜玩家 {玩家} 獲勝!') 輸贏平局 = '贏' break elif all(位置 == 'X' or 位置 == 'O' for 位置 in 井字盤): 印出井字盤(井字盤) print('平局!') 輸贏平局 = '平局' break 玩家 = 'O' if 玩家 == 'X' else 'X' else: print('輸入無效,請輸入1到9之間的數字。') if 輸贏平局 is None: print('遊戲結束。') if __name__ == '__main__': 主程式() ``` :::success 1|2|3 -+-+- 4|5|6 -+-+- 7|8|9 請玩家 X 輸入位置(1-9):5 1|2|3 -+-+- 4|X|6 -+-+- 7|8|9 請玩家 O 輸入位置(1-9):1 O|2|3 -+-+- 4|X|6 -+-+- 7|8|9 請玩家 X 輸入位置(1-9):4 O|2|3 -+-+- X|X|6 -+-+- 7|8|9 請玩家 O 輸入位置(1-9):8 O|2|3 -+-+- X|X|6 -+-+- 7|O|9 請玩家 X 輸入位置(1-9):6 O|2|3 -+-+- X|X|X -+-+- 7|O|9 恭喜玩家 X 獲勝! ::: ### 2.踩地雷 創建地雷地圖(行數, 列數, 地雷數): 生成一個地雷地圖,並在地雷位置標記為 'X'。 顯示遊戲地圖(遊戲地圖): 顯示遊戲地圖,玩家踩開的區域用 '□' 顯示。 檢查合法性(行, 列, 行數, 列數): 檢查座標是否合法。 計算周圍地雷數(地雷地圖, 行, 列): 計算指定位置周圍的地雷數。 檢查地雷(地雷地圖, 行, 列): 檢查指定位置是否有地雷。 顯示地雷地圖(地雷地圖): 顯示地雷地圖,用於在遊戲結束後顯示所有地雷位置。 整體主程式流程如下: 使用者輸入遊戲參數:行數、列數、地雷數。 生成地雷地圖並初始化遊戲地圖。 進入遊戲主迴圈: 使用者輸入檢查的位置。 檢查該位置是否合法。 若合法,檢查是否踩到地雷: 若踩到地雷,遊戲結束,顯示所有地雷位置。 若未踩到地雷,顯示周圍地雷數,繼續遊戲。 若不合法,提示重新輸入。 ```python= # 創造一個踩地雷遊戲呢? # 創建地雷地圖 # 顯示遊戲地圖 # 檢查合法性 # 計算周圍地雷數 # 檢查地雷 # 顯示地雷地圖 import random 中文數字 = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] def 創建地雷地圖(行數, 列數, 地雷數): 地雷地圖 = [['O' for _ in range(列數)] for _ in range(行數)] 隨機地雷位置 = random.sample(range(行數 * 列數), 地雷數) for 位置 in 隨機地雷位置: 行 = 位置 // 列數 列 = 位置 % 列數 地雷地圖[行][列] = 'X' return 地雷地圖 def 顯示遊戲地圖(遊戲地圖): for 行 in 遊戲地圖: print(' '.join(行)) def 檢查合法性(行, 列, 行數, 列數): return 0 <= 行 < 行數 and 0 <= 列 < 列數 def 計算周圍地雷數(地雷地圖, 行, 列): 周圍地雷數 = 0 鄰居方向 = [(1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)] for dx, dy in 鄰居方向: 新行, 新列 = 行 + dx, 列 + dy if 檢查合法性(新行, 新列, len(地雷地圖), len(地雷地圖[0])) and 地雷地圖[新行][新列] == 'X': 周圍地雷數 += 1 return 周圍地雷數 def 檢查地雷(地雷地圖, 行, 列): if 地雷地圖[行][列] == 'X': return True return False def 顯示地雷地圖(地雷地圖): for 行 in 地雷地圖: print(' '.join(行)) def 主程式(): print('歡迎來到踩地雷遊戲!') 行數 = int(input('請輸入行數:')) 列數 = int(input('請輸入列數:')) 地雷數 = int(input('請輸入地雷數:')) 地雷地圖 = 創建地雷地圖(行數, 列數, 地雷數) 遊戲地圖 = [['□' for _ in range(列數)] for _ in range(行數)] 顯示遊戲地圖(遊戲地圖) while True: #try: # 行 = int(input('請輸入行數(1-{0}): '.format(行數))) - 1 # 列 = int(input('請輸入列數(1-{0}): '.format(列數))) - 1 #except ValueError: # print('請輸入有效的數字。') # continue 位置 = input('請輸入要檢查的位置 (例如: 1,3):') try: 行, 列 = map(int, 位置.split(',')) 行 -= 1 列 -= 1 except ValueError: print('請輸入有效的位置 (例如: 1,3)。') continue if not 檢查合法性(行, 列, 行數, 列數) or 遊戲地圖[行][列] != '□': print('請輸入有效的行數和列數。') continue if 檢查地雷(地雷地圖, 行, 列): 顯示地雷地圖(地雷地圖) print('踩到地雷,遊戲結束!') break else: 周圍地雷數 = 計算周圍地雷數(地雷地圖, 行, 列) 遊戲地圖[行][列] = 中文數字[周圍地雷數] 顯示遊戲地圖(遊戲地圖) if __name__ == "__main__": 主程式() ``` :::success 歡迎來到踩地雷遊戲! 請輸入行數:10 請輸入列數:10 請輸入地雷數:90 □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ 請輸入要檢查的位置 (例如: 1,3):3,1 X X X X X X X X O X O X X X X X X X O X X O X X X X X X X X X X O X X X X X O X X X X X X X X X X X X X X X X X X O X O X X X X X X X X X X X X X X X X X X X X X X X X X X O X X O X X X X X X X X X X 踩到地雷,遊戲結束! ::: ### 3.猜數字幾A幾B ```python= import random def 生成祕密數字(): # 生成一個四位不重複的數字作為祕密數字 數字列表 = [str(i) for i in range(10)] random.shuffle(數字列表) return ''.join(數字列表[:4]) def 獲取猜測(): while True: # 輸入玩家的猜測,確保輸入的是四位不重複的數字 猜測 = input("請猜一個四位數字(數字不重複):") if len(猜測) == 4 and 猜測.isdigit() and len(set(猜測)) == 4: return 猜測 print("無效的輸入!") def 獲取提示(猜測, 祕密數字): # 檢查猜測和祕密數字的相符情況,並返回提示字串 A的數量 = sum(1 for a, b in zip(猜測, 祕密數字) if a == b) B的數量 = sum(1 for g in 猜測 if g in 祕密數字) - A的數量 return f"{A的數量}A{B的數量}B" def 遊戲開始(): # 初始化遊戲,生成祕密數字 祕密數字 = 生成祕密數字() 嘗試次數 = 0 while True: # 玩家進行猜測 猜測 = 獲取猜測() 嘗試次數 += 1 if 猜測 == 祕密數字: # 猜對時結束遊戲,顯示結果 print(f"恭喜你猜對了!答案就是 {祕密數字}。你總共猜了 {嘗試次數} 次。") break 提示 = 獲取提示(猜測, 祕密數字) print(f"提示:{提示}") if __name__ == "__main__": # 啟動遊戲 遊戲開始() ``` :::success 提示:0A1B 提示:1A1B 提示:1A1B 提示:1A1B ::: ## 11/14運用Python進行機器學習 ```pyhton= # 生成兩個圓形的數據點,並以散點圖的形式呈現。其中,generate_circle_points 函數用於生成在指定半徑範圍內均勻分布的圓形點。程式碼使用Matplotlib進行繪圖,其中兩個圓形的數據點分別以藍色和橙色的散點表示,並且加入了相應的標籤和標題。 import matplotlib.pyplot as plt import numpy as np # 定義生成圓形點的函數 def generate_circle_points(r_min, r_max, num_points): angles = np.random.uniform(0, 2 * np.pi, num_points) radii = np.sqrt(np.random.uniform(r_min**2, r_max**2, num_points)) x = radii * np.cos(angles) y = radii * np.sin(angles) return x, y # 定義圓形的半徑範圍和數據點數量 R0 = 0 R1 = 2 R2 = 1 R3 = 3 N = 200 # 原始點的數量 # 生成兩個圓形的數據點 x_o, y_o = generate_circle_points(R0, R1, N) x_x, y_x = generate_circle_points(R2, R3, N) # 繪製散點圖 plt.figure(figsize=(8, 8)) plt.scatter(x_o, y_o, c='blue', marker='o', label='Positive O') plt.scatter(x_x, y_x, c='orange', marker='o', label='Negative O') plt.xlabel('X') plt.ylabel('Y') plt.title('Scatter Plot with Different Classes') plt.legend() plt.grid(True) plt.axis('equal') plt.show() ``` ![download](https://hackmd.io/_uploads/HJaUVYF4a.png) ```python= import matplotlib.pyplot as plt import numpy as np def plot_predictions(X_train, y_train, X_test, y_test, model): # 使用模型對訓練集進行預測 y_pred_train_continuous = model.predict(X_train) y_pred_train = np.where(y_pred_train_continuous.flatten() >= 0, 1, -1) # 使用模型對測試集進行預測 y_pred_test_continuous = model.predict(X_test) y_pred_test = np.where(y_pred_test_continuous.flatten() >= 0, 1, -1) plt.figure(figsize=(8, 8)) # 訓練集 - 預測正確 correct_train = (y_train == y_pred_train) oc = (y_train == 1) & correct_train xc = (y_train == -1) & correct_train plt.scatter(X_train[oc, 0], X_train[oc, 1], c='blue', marker='o', label='Train Correct (Positive)') plt.scatter(X_train[xc, 0], X_train[xc, 1], c='orange', marker='o', label='Train Correct (Negative)') # 訓練集 - 預測錯誤 incorrect_train = (y_train != y_pred_train) oi = (y_train == 1) & incorrect_train xi = (y_train == -1) & incorrect_train plt.scatter(X_train[oi, 0], X_train[oi, 1], c='blue', marker='x', label='Train Incorrect (Positive)') plt.scatter(X_train[xi, 0], X_train[xi, 1], c='orange', marker='x', label='Train Incorrect (Negative)') # 測試集 - 預測正確 correct_test = (y_test == y_pred_test) oc = (y_test == 1) & correct_test xc = (y_test == -1) & correct_test plt.scatter(X_test[oc, 0], X_test[oc, 1], c='cyan', marker='o', label='Test Correct (Positive)') plt.scatter(X_test[xc, 0], X_test[xc, 1], c='pink', marker='o', label='Test Correct (Negative)') # 測試集 - 預測錯誤 incorrect_test = (y_test != y_pred_test) oi = (y_test == 1) & incorrect_test xi = (y_test == -1) & incorrect_test plt.scatter(X_test[oi, 0], X_test[oi, 1], c='cyan', marker='x', label='Test Incorrect (Positive)') plt.scatter(X_test[xi, 0], X_test[xi, 1], c='pink', marker='x', label='Test Incorrect (Negative)') plt.xlabel('X Coordinate') plt.ylabel('Y Coordinate') plt.title('Model Predictions') plt.legend() plt.grid(True) plt.show() ``` ```python= # 整合並標記數據點 X = np.vstack((np.column_stack((x_o, y_o)), np.column_stack((x_x, y_x)))) y = np.array([1] * N + [-1] * N) # 1代表o,-1代表x # 分割數據集, 把 N 中的 20% 做為測試 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 創建神經網路模型 N1 = 3 model = Sequential() model.add(Dense(N1, input_dim=2, activation='tanh')) # 第一層有N1個神經元,使用tanh激活函數 model.add(Dense(2, input_dim=2, activation='tanh')) # 第二層有2個神經元 model.add(Dense(1, activation='tanh')) # 第三層有1個神經元 # 編譯模型 model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy']) ``` ```python= # 訓練模型並記錄訓練過程 history = model.fit(X_train, y_train, epochs=1000, batch_size=5, verbose=0, validation_data=(X_test, y_test)) # 獲取損失函數值 loss_values = history.history['loss'] # 繪製損失函數圖 plt.figure(figsize=(8, 4)) plt.plot(loss_values, label='Training Loss') plt.xlabel('Epoch') plt.ylabel('Loss') plt.title('Loss Function During Training') plt.legend() plt.grid(True) plt.show() # 获取训练和验证集准确度 # train_acc = history.history['accuracy'] # val_acc = history.history['val_accuracy'] # 绘制准确度图 #plt.figure(figsize=(8, 4)) #plt.plot(train_acc, label='Training Accuracy') #plt.plot(val_acc, label='Validation Accuracy') #plt.xlabel('Epoch') #plt.ylabel('Accuracy') #plt.title('Model Accuracy during Training') #plt.legend() #plt.grid(True) #plt.show() plot_predictions(X_train, y_train, X_test, y_test, model) # 獲取第一層的權重和偏置 weights, biases = model.layers[0].get_weights() # 生成更多隨機點進行預測 x_a, y_a = generate_circle_points(R0, R3, Np) additional_X = np.column_stack((x_a, y_a)) y_pred_additional = model.predict(additional_X) y_pred_additional = np.where(y_pred_additional.flatten() >= 0, 1, -1) # 繪製測試數據和預測結果 plt.figure(figsize=(8, 8)) plt.scatter(x_o, y_o, c='blue', marker='o', label='Class Positive') plt.scatter(x_x, y_x, c='orange', marker='o', label='Class Negative') plt.scatter(additional_X[y_pred_additional == 1, 0], additional_X[y_pred_additional == 1, 1], c='blue', marker='o', label='Predicted Positive') plt.scatter(additional_X[y_pred_additional == -1, 0], additional_X[y_pred_additional == -1, 1], c='orange', marker='o', label='Predicted Negative') # 繪製第一層的N1條直線 x_values = np.linspace(-2, 2, 100) y_values = np.linspace(-2, 2, 100) for i in range(N1): a, b = weights[:, i] c = biases[i] if abs(a) > abs(b): x_line = (-b * y_values - c) / a plt.plot(x_line, y_values, linestyle='--', label=f'Neuron {i+1} Boundary') else: y_line = (-a * x_values - c) / b plt.plot(x_values, y_line, linestyle='--', label=f'Neuron {i+1} Boundary') plt.xlabel('X') plt.ylabel('Y') plt.title('Additional Points Classification with Neuron Boundaries') plt.legend() plt.grid(True) plt.axis('equal') plt.show() ``` ![download](https://hackmd.io/_uploads/SyV7BYKNa.png) ![download](https://hackmd.io/_uploads/HyF7rYtVT.png) :::info 在二元分類(Binary Classification)的混淆矩陣(Confusion Matrix)中,常見的術語包括: 1. **True Positive (TP):** 正樣本被正確地分類為正類。在這裡,指的是模型正確地預測為正類的實例數。 2. **True Negative (TN):** 負樣本被正確地分類為負類。在這裡,指的是模型正確地預測為負類的實例數。 3. **False Positive (FP):** 負樣本被錯誤地分類為正類。在這裡,指的是模型錯誤地將實際為負類的樣本預測為正類的實例數。 4. **False Negative (FN):** 正樣本被錯誤地分類為負類。在這裡,指的是模型錯誤地將實際為正類的樣本預測為負類的實例數。 這些術語的組合形成了混淆矩陣: \[ \begin{array}{cc|c} & & \text{實際} \\ & & \text{正類} & \text{負類} \\ \hline \text{預測} & \text{正類} & TP & FP \\ & \text{負類} & FN & TN \\ \end{array} \] 進一步的評估指標: 當進行二元分類(Binary Classification)時,混淆矩陣(Confusion Matrix)是一個用來評估模型性能的重要工具,其中包含了以下術語: 1. **True Positive (TP):** 正樣本被正確地分類為正類。指的是模型正確地預測為正類的實例數。 2. **True Negative (TN):** 負樣本被正確地分類為負類。指的是模型正確地預測為負類的實例數。 3. **False Positive (FP):** 負樣本被錯誤地分類為正類。指的是模型錯誤地將實際為負類的樣本預測為正類的實例數。 4. **False Negative (FN):** 正樣本被錯誤地分類為負類。指的是模型錯誤地將實際為正類的樣本預測為負類的實例數。 混淆矩陣的形式如下: \[ \begin{array}{ccc} & \text{實際正類} & \text{實際負類} \\ \hline \text{預測正類} & TP & FP \\ \text{預測負類} & FN & TN \\ \end{array} \] 這裡還有一些常見的評估指標: - **Accuracy (ACC):** 分類器正確預測的比例,計算方式為 $( \frac{{TP + TN}}{{TP + TN + FP + FN}} )$. - **True Positive Rate (TPR), Sensitivity, Recall:** 正類實例中被分類為正類的比例,計算方式為 $( \frac{{TP}}{{TP + FN}} )$. - **True Negative Rate (TNR), Specificity:** 負類實例中被分類為負類的比例,計算方式為 $( \frac{{TN}}{{TN + FP}} \)$. - **False Positive Rate (FPR):** 負類實例中被誤分正類的比例,計算方式為$( 1 - \text{TNR} \) 或 \( \frac{{FP}}{{TN + FP}} )$. - **False Negative Rate (FNR):** 正類實例中被誤分為負類的比例,計算方式為 $( 1 - \text{TPR} \) 或 \( \frac{{FN}}{{TP + FN}} )$. - **Precision (Positive Predictive Value, PPV):** 被分類為正類的實例中真正為正類的比例,計算方式為 $( \frac{{TP}}{{TP + FP}} )$. - **Negative Predictive Value (NPV):** 被分類為負類的實例中真正為負類的比例,計算方式為 $( \frac{{TN}}{{TN + FN}} )$. - **F1 Score:** 精確度和召回率的調和平均值,計算方式為 $( \frac{{2 \cdot \text{PPV} \cdot \text{TPR}}}{{\text{PPV} + \text{TPR}}} )$. ::: ```python= #loss, accuracy = model.evaluate(X_train, y_train) #print('train loss: ', loss) #print('train accuracy: ', accuracy) y_pred_train_continuous = model.predict(X_train) y_pred_train = np.where(y_pred_train_continuous.flatten() >= 0, 1, -1) TP = sum((y_pred_train==1) & (y_train == 1)) TN = sum((y_pred_train==-1) & (y_train == -1)) FP = sum((y_pred_train==1) & (y_train == -1)) FN = sum((y_pred_train==-1) & (y_train == 1)) print("In training set:") TPR = TP/(TP+FN) TNR = TN/(TN+FP) FPR = 1-TNR FNR = 1-TPR PPV = TP/(TP+FP) NPV = TN/(TN+FN) F1 = 2*PPV*TPR/(PPV+TPR) ACC = (TP+TN)/(TP+TN+FP+FN) print("TP=",TP,"TN=",TN,"FP=",FP,"FN=",FN) print("Accuracy=",ACC) print("TPR(Sensitivity, Recall)=",TPR,"TNR(Specificity)=",TNR) #loss, accuracy = model.evaluate(X_test, y_test) #print('test loss: ', loss) #print('test accuracy: ', accuracy) #y_pred_test_continuous = model.predict(X_test) #y_pred_test = np.where(y_pred_test_continuous.flatten() >= 0, 1, -1) ``` :::success 10/10 [==============================] - 0s 2ms/step In training set: TP= 156 TN= 134 FP= 30 FN= 0 Accuracy= 0.90625 TPR(Sensitivity, Recall)= 1.0 TNR(Specificity)= 0.8170731707317073 :::