R 小筆記

Realtek 公司也簡稱 R, 不過應該沒有多少人用過 R 語言. 最近適逢要用到 regression model, 但網路課程幾乎都是用 R (歷史包袱), 而不是 Python, 所以我也試著瞭解用 R 來理解 regression model.

首先 library(UsingR) 載入基本套件, 然後用 x 來 predict y.

y = β0 + β1 * X

在程式中, 以 beta0 取代 β0 , 而 beta1 取代β 1 , 因為我們只是 predict, 並不是 assign 值給 y, 所以要求的是 minimum square error.

i=1n​(Yi−(β0​+β1Xi))2

為了增加趣味性, 課程舉例是用父母的身高預測小孩的身高. 我們可以理解到身高不會為 0, 所以有一個 beta0 撐著, 然後父母身高 X 乘上的 weighting beta1, 就可以預測小孩的身高. 當然, 我們又可以理解到這是在統計上才有意義, 對個案沒有意義.

lm(y~x) 就可以得到用 x 預測 y 的 linear model 的結果.

coef(lm(y~x)) 回報 coefficients beta0 和 beta1.

c(beta0, beta1) 用來產生向量.

舉例來說, x 和 y 用 c() 產生向量, 得出 linear model 後, model 再用 coef() 取出係數, 然後印出來.


x <- c(1, 2, 3, 4, 5)
y <- c(2, 3, 5, 7, 11)

# 建立線性回歸模型
model <- lm(y ~ x)

# 獲取模型係數
coefficients <- coef(model)  # This gives c(beta0, beta1)

intercept <- coefficients[1] # beta0
slope <- coefficients[2] # beta1

# 印模型係數
print(intercept)
print(slope)

# OR 一行印模型係數
print(coefficients)

其中 <- 表示 assign, 正式名稱為賦值運算子 (assignment operator), 和 C 的 pointer 反方向.

用 Python 其實也不會變囉嗦. 以這個例子來說, Python 可以輕鬆應對. 雖然 R 確實更簡潔一點點.

import numpy as np
from sklearn.linear_model import LinearRegression

x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 3, 5, 7, 11])

# 建立線性回歸模型
model = LinearRegression()
model.fit(x.reshape(-1, 1), y)

# 獲取模型係數
intercept = model.intercept_
slope = model.coef_[0]

# 印模型係數
print(f"Intercept (beta0): {intercept}")
print(f"Slope (beta1): {slope}")

# OR 一行印模型係數
print(model)
 

少年 Py 的奇幻漂流

週日晚上做了一個夢。有位老先生用毛筆字寫了封信給我,署名林如松,要我照顧他的兒子。說這個兒子學習不好是因為某種心理疾病吧!總之懇請多多照顧等有上百來字。望文生義,那麼我在夢中的身份就是個導師了。

身為導師, 而不是醫師。我開始找醫學相關的線索。在一張可能是精神科醫師的桌子上,我發現了名片。上面寫了幾個小字說明醫師的專業。細節忘了,但其中 “止冰" 兩個字清楚地印入我的眼簾。這是什麼? 要阻止冰塊? 還是冰毒? 我納悶了一會兒,才恍然大悟是"治病" 的諧音.

病人因為精神疾病來求診,有點害羞會不想讓人知道,所以醫師就用某某人止冰來隱晦這件事! 想不到我只是做個夢,也會自編自導諧音梗啊! 在我破解了自己的梗之後,空中又傳來一個自問自答。"為什麼脖子太長不好? " 隔了一下,"因為好"頸" (景) 不長 (常)"。看來我的夢境是進入了諧音梗的 decorator [1].

等等! 一開始我有正經任務的啊! 怎麼跑題了? 想到這裡,世界又變得緊張嚴肅了。好像是初三23:59’57″ – 快初四 (出事)了! 我帶著兩三個人開始闖關,其中也不知道有沒有包括林小弟? 總之系統瞬間提示倒數 3 秒鐘,如果不在限時內讓機關套住一個掛勾,在我後面的人都會從平台上滑下去。正當我回頭叫其他人跟上來,倒數 3 秒已經 “加速" 結束了。我能跟大家說的話只有 一句 “來不及了"。

然而,即使倒數時間到了,我沒有完成任務,其他人也沒跟上,但好像並沒有發生什麼了不起的事? What not happened? 難道因為我們的 3 秒不是真的 3 秒,Dead line 也就不是 line 了嗎 ? 換言之,line 變成 non-linear,所以 dead 也就不 dead 了 !? 這麼一想好像也有道理。好比 nonlocal [2] 如字面所說,雖然不是 global,但肯定不是 local。事前有舖梗,後面就拗得過去。

看來這個夢中世界的 “人設" 很不靠譜啊!? 果然畫面再一轉,出現了那位忘記是自稱還是人稱喇賽之王的前同事 “肯", 帶著我們一行人小跑步穿越著商店街。沒有要 shopping,就是路過著日常騎樓下攤販。本來好像要堂堂展開的華麗冒險,就這樣被 apply(荒謬且搞笑) [3] 了.

Anyway,不管發生什麼事,我們都可以正向解讀。其實我們這位前同事去了谷歌。也許我祖先周公暗示著不管局勢多麼奇幻,還是要好好探索 (Google) 一下未知的領域。那些小攤位就不逛了,我們繼續前行,找出更重要的線索。既解決林小弟的困擾,幫助那位老林先生,同時也完成自己的任務。

[REF]

1. 在 Python 中,裝飾器(decorator) 的作用是用來修改或增強函數的行為。當你使用裝飾器時,原函數會被包裝到一個新的函數(通常是內部的 wrapper_func)中,因此裝飾器會影響函數的執行方式。例如:

      from datetime import datetime
      
      def 計時器(func):
          def wrapper():
              現在時間 = datetime.now()
              小時 = 現在時間.hour
              print (小時, "點了")
              func()
          return wrapper
      
      @計時器
      def 打招呼():
          print("你好!")
      
      打招呼()

      2. 在 Python 中,nonlocal 關鍵字用於在嵌套函數中聲明變數,讓內層函數可以修改外層(但非全局)作用域中的變數。

      def 按讚():
          
          次數 = 0
       
          def comment_filter(好評):
              nonlocal 次數
      
              總類 = ["讚", "愛心", "加油"]
              if 好評 in 總類:
                  次數 +=1
      
              print(f"好評 {次數}")
          return comment_filter
      
      按 = 按讚()
      按("哭")
      按("愛心")

      3. .apply() 主要在 Pandas 中使用,是一個非常強大的函數,用於對 DataFrame 或 Series 進行數據處理。例如: df[‘成績’].apply(加分)

      import pandas as pd
      import math
      
      data = {
          '姓名': ['林明明', '李大同', '王小美'],
          '成績': [85, 92, 5]
      }
      
      def 加分(row):
          # 取得成績值
          score = row['成績']
          # 計算新成績
          new_score = math.sqrt(score) * 10
          return new_score
      
      # 建立 DataFrame
      df = pd.DataFrame(data)
      
      # 使用 apply 並傳遞整個 DataFrame
      df['新成績'] = df.apply(加分, axis=1) 
      
      print("DataFrame 內容:")
      print(df)

      自製 mini ChatGPT

      根據 [1], 決定自製一個 mini ChatGPT. Afiz 的流程如下:

      首先在 Anaconda 中 pip install openai 就失敗, 原來要用 conda install -c conda-forge openai [2].

      pip install gradio 沒問題

      from config open_api_key 一看就不合用! 看 [2] 裡面的說明, 要先參加 OpenAI會員. 這個我已經註冊過了. 登入後, 可以在 https://beta.openai.com/account/api-keys 產生 key. 然後把 key 設為環境變數 %OPENAI_API_KEY%.

      後面照抄 [4], 可是出現 check internet connection. 暫時卡住.

      這要怎麼 debug 呢? 因為是抄的, 所以有點不明就裡. 乾脆來問 ChatGPT 本人要怎麼呼叫它? 然後它就大方地給我一個 sample code. 這感覺就是 “玄 “!

      import os
      import openai
      
      openai.api_key = os.getenv("OPENAI_API_KEY")
      response = openai.Completion.create(
          model="text-davinci-003",
          prompt="The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly.\n\nHuman: Hello, who are you?\nAI: I am an AI created by OpenAI. How can I help you today?\nHuman: I'd like to cancel my subscription.\nAI:",
      
          temperature=0.9,
          max_tokens=150,
          top_p=1,
          frequency_penalty=0.0,
          presence_penalty=0.6,
          stop=[" Human:", " AI:"]
      )
      

      不過, 這段程式還是有個相容性問題. 它說 Anacoda 裡面有段 source code 開檔預設是 latin-1, 不是 UTF-8. 這…這我 debug 不了啊? 查一下午資料, 都說要改 mysql database 那邊的設定.

      UnicodeEncodeError: 'latin-1' codec can't encode character '\u201c' in position 7: ordinal not in range(256)

      好在我到處 Google 找到了另外一篇中文教學 [5], 它的範例不會打到上面那個 bug. 所以狗哥不用怕, 裁員一次就好, ChatGPT 暫時還不能把你幹掉. 仔細比較兩個程式, 目前認為還是 export private key 沒有成功, 所以暫時用明碼才能夠連線的關係. 這樣總算在過年假期當中, 把 OpenAI 的探索前進了一小步! 現在它可以講笑話了, 雖然要等 2~3 秒.

      [REF]

      1. https://twitter.com/itsafiz/status/1610245691812741120
      2. https://anaconda.org/conda-forge/openai
      3. https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety
      4. https://github.com/afizs/chatgpt-clone/blob/main/mini_ChatGPT.ipynb
      5. https://steam.oxxostudio.tw/category/python/example/openai.html

      LeetCode 小體驗

      話說我摸了一陣子 Python, 那要算會? 還是不會呢? 稍微 Google了一下相關資料, 臉書的廣告就變成各種 Python 補習班了. 當然, 要我花錢去補習或是考照那是絕不可能的! 好歹我還曾經贓到過 Sun 認證的第一代 Java 講師稱號呢, 怎麼可以從講師變學徒呢? 至少要自修吧! 哈! 但是誰可以幫我鑑定一下我的水準呢? 我靈機一動就想到了 LeetCode.

      如果我用 Python 來解 LeetCode 的題目 [1], 不就知道自己的水準好不好了嗎? 於是乎我找出註冊 N 年還沒開工過的 LeetCode 帳號, 選用 Python3 來作答. …..嗯, 果然程度不太好. 雖然看過一些 code, 也把教學 [2] 讀完了. 不過還是不能得心應手.

      尤其第一次做, 我還不知道題目下面就有 test case, 也不知道不用自己寫輸出入 UI, 只要 function 吃到參數就好. 所以花了很多時間設計怎麼輸入 list 最 user friendly, 結果不但做白工, 還判失敗~~ 結果拔一拔反而 pass 了. 完全在搞笑!

      所以提醒初學者, 先選選擇難度. 然後挑個自己想解的題目.

      點進去之後. 可以選各種語言. 下面有 test case. 右下角選 run, 然後看 Result 對不對? 對的話就可以按綠色的 Submit. 如果選 auto, 電腦可以自動幫忙完成, 當然那也要花錢錢. 點選題目也可以看別人的解答, Stackoverflow 也一堆解答. 不過我第一個程式當然要自己摸索~~ (當然也就搞笑了).

      Accept 之後, 系統還會說明執行速度和使用 memory 兩方面贏過多少人? 這個要拚的話當然是可以再努力. 不要 init class 也可以變快一點 (^^). 另外, 我傻傻地用初學時的 Jupyter Notebook 打草稿, 這樣連 list 都要 import 才編得過. 但是在 LeetCode 卻都可以忽略. 果然是有差!

      Anyway, 我第一次 run LeetCode, 而且是用 Python. 這還滿值得我記錄的, 算是 2023 年的新年新把戲!

      [REF]

      1. https://leetcode.com/problemset/all/
      2. https://docs.python.org/zh-tw/3/tutorial/index.html