---
# System prepended metadata

title: Python 課堂筆記

---

# Python 課堂筆記2

## 10/17

### 了解複利並計算其利息、<br>本利和及每日利息在有無四捨五入的情況下如何影響本利和
```py=
# 輸入資訊
P = 1000  # 假設本金為1000元
r = 0.03  # 年利率為3%
n = 365   # 每天複利一次
t = 1     # 1年

# 計算本利和
A = P * (1 + r/n)**(n*t)

# 輸出結果
print("一年後的本利和為:", A)
```

```pytho=
# 輸入資訊
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)
```
```oython=
# 輸入資訊
P = 1000  # 假設本金為1000元
r = 0.03  # 年利率為3%
n = 365   # 每天複利一次
t = 1     # 1年

# 計算每日利息和本利和（有四捨五入）
A_with_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)

# 計算每日利息和本利和（無四捨五入）
A_without_rounding = P
for _ in range(n*t):
    daily_interest = A_without_rounding * (r/n)
    A_without_rounding += daily_interest

# 輸出結果
print("有四捨五入的本利和為:", A_with_rounding)
print("無四捨五入的本利和為:", A_without_rounding)

# 比較兩者差異
difference = A_with_rounding - A_without_rounding
print("有四捨五入與無四捨五入的差異為:", difference)
```

### 如何利用Python繪圖
最常用的是matplotlib和seaborn，它們可以用來創建各種類型的圖表。
以下是一個簡單的示例，演示如何使用matplotlib庫創建一個簡單的折線圖：

首先，確保已經安裝了matplotlib庫。如果沒有安裝，可以使用以下命令安裝：
```python=
pip install matplotlib
```
然後，您可以使用以下代碼創建一個簡單的折線圖：
```python=
import matplotlib.pyplot as plt

# 創建數據
x = [1, 2, 3, 4, 5]
y = [10, 12, 5, 8, 9]

# 創建折線圖
plt.plot(x, y)

# 添加標籤和標題
plt.xlabel('X軸標籤')
plt.ylabel('Y軸標籤')
plt.title('簡單折線圖')

# 顯示圖形
plt.show()
```
以下是將上面提到的計算使用Python圖像化
```python=
import matplotlib.pyplot as plt

# 計算每個本金 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("本金 P")
plt.ylabel("四捨五入和無四捨五入的差異")
plt.title("本金 P 對差異的影響")
plt.grid(True)
plt.show()

```

```python=
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]
    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('time')
plt.ylabel('population')
plt.title('Logistic model')
plt.grid(True)
plt.show()

```

## 10/24 
### 網路爬蟲
1. 安裝Python和相關套件
首先，需要安裝Python解釋器和相關的套件
```python=
# 安裝 requests 和 BeautifulSoup
pip install requests beautifulsoup4
```
2. 使用 requests 獲取網頁內容
```python=
import requests

url = 'https://example.com'
response = requests.get(url)

# 檢查是否成功獲取網頁
if response.status_code == 200:
    html_content = response.text
    print(html_content)
else:
    print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
```
3. 使用 BeautifulSoup 解析HTML
```python=
from bs4 import BeautifulSoup

# 創建BeautifulSoup對象
soup = BeautifulSoup(html_content, 'html.parser')

# 獲取網頁標題
title = soup.title.text
print(f"Title: {title}")

# 獲取所有的超鏈接
links = soup.find_all('a')
for link in links:
    print(link.get('href'))
```
4. 實作簡單的網路爬蟲
```python=
# 這是一個簡單的例子，從網頁中提取新聞標題
news_titles = soup.find_all('h2', class_='news-title')
for title in news_titles:
    print(title.text)
```


## 10/31 
### 影像處理
1. 安裝相關工具和套件
```python=
# 安裝常用的影像處理套件
pip install opencv-python
pip install matplotlib
```
2. 開始影像處理 讀取和顯示影像
```python=
import cv2
import matplotlib.pyplot as plt

# 讀取影像
image_path = 'path/to/your/image.jpg'
image = cv2.imread(image_path)

# OpenCV使用BGR色彩表示，轉換成RGB用於顯示
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 顯示原始影像
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')
plt.show()
```
3. 影像轉灰階
```python=
# 將影像轉灰階
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 顯示灰階影像
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale Image')
plt.axis('off')
plt.show()
```
4. 兩張圖並列
```python=
# 顯示兩張圖片並列
plt.subplot(1, 2, 1)
plt.imshow(image1_rgb)
plt.title('Image 1')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(image2_rgb)
plt.title('Image 2')
plt.axis('off')

plt.show()

```
5. 兩張圖合併
```python=

# 假設兩張圖片大小相同
merged_image = cv2.addWeighted(image1, 0.5, image2, 0.5, 0)

# 顯示合併後的圖片
plt.imshow(cv2.cvtColor(merged_image, cv2.COLOR_BGR2RGB))
plt.title('Merged Image')
plt.axis('off')
plt.show()
```

6. 替換背景
```python=
# 讀取背景圖片
background_path = 'path/to/your/background.jpg'
background = cv2.imread(background_path)

# 調整背景大小和原始圖片相同
background = cv2.resize(background, (image1.shape[1], image1.shape[0]))

# 假設要替換的區域是矩形範圍 (x, y, width, height)
roi = merged_image[y:y+height, x:x+width]

# 在背景上放置替換的區域
background[y:y+height, x:x+width] = roi

# 顯示替換背景後的圖片
plt.imshow(cv2.cvtColor(background, cv2.COLOR_BGR2RGB))
plt.title('Image with Replaced Background')
plt.axis('off')
plt.show()
```
## 11/7 
### 製作小遊戲
1. 小遊戲範例--井字遊戲
```python=

# 設計井字遊戲需要以下的函數
#  印出井字盤
#  檢查贏家
#  主程式

def 印出井字盤(井字盤):
    print(井字盤[0] + '|' + 井字盤[1] + '|' + 井字盤[2])
    print('-+-+-')
    print(井字盤[3] + '|' + 井字盤[4] + '|' + 井字盤[5])
    print('-+-+-')
    print(井字盤[6] + '|' + 井字盤[7] + '|' + 井字盤[8])

def 檢查贏家(井字盤, 符號):
    贏的組合 = [
        [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 Ture = 一直跑下去
    while True:
        印出井字盤(井字盤)
        輸入位置 = input(f'請玩家 {玩家} 輸入位置（1-9）：')

        if 輸入位置.isdigit() and 1 <= int(輸入位置) <= 9:
            輸入位置 = int(輸入位置) - 1
            if 井字盤[輸入位置] == 'X' or 井字盤[輸入位置] == 'O':
                print('該位置已被佔據，請重新輸入。')
            else:
                井字盤[輸入位置] = 玩家
                if 檢查贏家(井字盤, 玩家):
                    印出井字盤(井字盤)
                    print(f'恭喜玩家 {玩家} 獲勝！')
                    輸贏平局 = '贏'
                    break  # 跳出while-loop
                elif all(位置 == 'X' or 位置 == 'O' for 位置 in 井字盤):
                    印出井字盤(井字盤)
                    print('平局！')
                    輸贏平局 = '平局'
                    break  # 跳出while-loop
                玩家 = 'O' if 玩家 == 'X' else 'X'
        else:
            print('輸入無效，請輸入1到9之間的數字。')

    if 輸贏平局 is None:
        print('遊戲結束。')

if __name__ == '__main__':
    主程式()
```

2. 小遊戲範例--踩地雷
```python=
# 創造一個踩地雷遊戲呢?
#  創建地雷地圖
#  顯示遊戲地圖
#  檢查合法性
#  計算周圍地雷數
#  檢查地雷
#  顯示地雷地圖

import random

中文數字 = ['０', '１', '２', '３', '４', '５', '６', '７', '８', '９']

def 創建地雷地圖(行數, 列數, 地雷數):
    地雷地圖 = [['Ｏ' for _ in range(列數)] for _ in range(行數)]
    隨機地雷位置 = random.sample(range(行數 * 列數), 地雷數)

    for 位置 in 隨機地雷位置:
        行 = 位置 // 列數
        列 = 位置 % 列數
        地雷地圖[行][列] = 'Ｘ'

    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 地雷地圖[新行][新列] == 'Ｘ':
            周圍地雷數 += 1

    return 周圍地雷數

def 檢查地雷(地雷地圖, 行, 列):
    if 地雷地圖[行][列] == 'Ｘ':
        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__":
    主程式()
```

3. 小遊戲範例--猜數字


```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__":
  遊戲開始()
```
### 自己改過的小遊戲--猜數字
將猜四位數改成猜五位數，在每次猜完之後多生成正確數字的位置以及不正確位置但正確的數字有哪些，大幅降低遊戲難度 還有在一開始就顯示出答案，方便檢查有沒有寫錯
```python=
import random

#產生數字
def generate_number():
    numbers = list(range(1, 10))
    random.shuffle(numbers)
    return ''.join(map(str, numbers[:5]))

#檢查答案&給提示
def evaluate_guess(secret_number, guess):
    a = b = 0
    display_guess = ['X', 'X', 'X', 'X', 'X']

    for i in range(5):
        if guess[i] == secret_number[i]:
            a += 1
            display_guess[i] = guess[i]
        elif guess[i] in secret_number:
            b += 1

    return a, b, display_guess

#主程式
def main():
    secret_number = generate_number()
    attempts = 0
    print(f"The secret number is: {secret_number}")

    print("Welcome to the Number Guessing Game (5-digit number)!")

    while True:
        guess = input("Enter a 5-digit number (digits must be unique): ")
        #檢查是否皆為數字和是否為五位數
        if len(guess) != 5 or not guess.isdigit():
            print("Please enter a valid 5-digit number.")
            continue
        #檢查數字是否重複
        if len(set(guess)) != 5:
            print("Digits must be unique.")
            continue

        attempts += 1
        a, b, display = evaluate_guess(secret_number, guess)
        #給予提示
        print(f"{' '.join(display)} (B includes {', '.join(set(guess) & set(secret_number))})")
        print(f"{a}A{b}B")

        if a == 5:
            print(f"Congratulations! You've guessed the number ({secret_number}) in {attempts} attempts!")
            play_again = input("Play again? (yes/no): ").lower()
            if play_again != "yes":
                break

if __name__ == "__main__":
    main()
```
## 11/14

### 神經網路概述
*以下為詢問ChatGPT
1. 神經元（Neurons）： 就像大腦中的神經元一樣，神經網路中的神經元接收輸入，進行計算，並生成輸出。

2. 層（Layers）： 神經網路由不同層組成。輸入層接收數據，輸出層生成預測結果，中間的層被稱為隱藏層。

3. 權重（Weights）和偏差（Biases）： 神經元之間的連接有權重控制，每個神經元還有一個偏差，這些值在學習中被調整。

4. 激活函數（Activation Functions）： 在神經元進行計算後，應用激活函數，引入非線性，使神經網路能夠學習更複雜的模式。

5. 隱藏層（Hidden Layers）： 這些層位於輸入和輸出層之間，用於學習複雜的特徵。多個隱藏層組成深度神經網路。

6. 前向傳播（Forward Propagation）： 數據通過網絡，每層進行計算，最終生成預測結果。

7. 反向傳播（Backward Propagation）： 通過比較預測和實際結果，計算誤差，然後逐層調整權重和偏差，使誤差最小化。

8. 損失函數（Loss Function）： 衡量模型預測與實際結果之間的差異，訓練過程中努力最小化這個差異。

### 利用Python機器學習
1. 安裝相關套件

```python=
pip install numpy pandas matplotlib scikit-learn
```
2. 資料準備
收集、清理、和準備資料是機器學習的重要一環。使用Pandas來載入和處理資料：
```python=
import pandas as pd

# 載入資料
data = pd.read_csv('your_dataset.csv')

# 探索資料
print(data.head())
```
3. 特徵工程
根據資料的特性，可能需要進行特徵工程，包括處理缺失值、編碼分類特徵、標準化數值特徵等：
```python=
from sklearn.preprocessing import StandardScaler

# 處理缺失值
data = data.dropna()

# 編碼分類特徵
data = pd.get_dummies(data, columns=['categorical_column'])

# 標準化數值特徵
scaler = StandardScaler()
data['numeric_column'] = scaler.fit_transform(data[['numeric_column']])
```
4. 模型選擇
選擇適當的機器學習模型，例如決策樹、支持向量機、隨機森林等。Scikit-learn提供了許多常用的機器學習算法：
```python=
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

# 分割訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(data.drop('target_column', axis=1), data['target_column'], test_size=0.2, random_state=42)

# 選擇模型
model = RandomForestClassifier()
```
5. 模型訓練
使用訓練集對模型進行訓練：
```python=
model.fit(X_train, y_train)
```
6. 模型評估
使用測試集評估模型的性能：
```python=
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

y_pred = model.predict(X_test)

print(f'Accuracy: {accuracy_score(y_test, y_pred)}')
print(f'Classification Report:\n{classification_report(y_test, y_pred)}')
print(f'Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}')
```
7. 預測
使用模型進行新數據的預測：
```python=
new_data = pd.read_csv('new_data.csv')
predictions = model.predict(new_data)
print(predictions)
```

### 上課範例
這個範例是要做一個類似tensor flow playground的類神經網路分類器。

其中我們產生兩個分類

與原點距離R0到R1，Positive (藍色點)
與原點距離是R2到R3的，Negative (橘色點)
每一類各產生 N 個點供訓練用， 也各產生 Np 個點以標記出確定Positive的範圍
```python=
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_split

N = 200  # 原始點的數量
Np = 1200  # 額外點的數量

#
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
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()


```
```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()

```








