安裝imageio模組
pip install imageio
-
讀入圖像
使用imageio模組
imageio.imread 載入圖片
torch.from_numpy 轉為張量
import numpy as np import torch import imageio img_arr = imageio.imread('./bobby.jpg') #載入一張圖片 img = torch.from_numpy(img_arr) #先將img_arr轉成PyTorch張量(以img表示) img.shape |
torch.Size([720, 1280, 3])
由於PyTorch格式要求,之後需要轉置成 [3, 720, 1280]
cf.
使用PIL (Pillow模組)
Image.open 載入圖片
transforms.ToTensor() "圖片"轉為張量
from PIL import Image from torchvision import transforms img_arr = Image.open('./bobby.jpg') img = transforms.ToTensor()(img_arr) img.shape |
torch.Size([3, 720, 1280])
-
讀資料夾內檔案
os模組
import os
os.listdir(資料夾路徑) : 資料夾下所有檔案(含副檔名) 以list顯示 每個檔案一項
os.path.splitext(檔案名稱) : 將檔案名稱分為 檔名[0] 副檔名[1]
將image-cats資料夾中所有png檔案(全彩 256*256) 讀入最多100張到batch張量中
batch = torch.zeros(100, 3, 256, 256, dtype=torch.uint8) #創一個 100張 全彩 256*256 的張量 import os filenames = [name for name in os.listdir('./image-cats/') if os.path.splitext(name)[1] == '.png'] for i, filename in enumerate(filenames): #依序載入每個png檔 (必須都是全彩256*256的) img_arr = imageio.imread('./image-cats/'+ filename) #filename格式是str img_t = torch.from_numpy(img_arr) img_t = img_t.permute(2, 0, 1) #調整張量中各軸的排列順序 batch[i] = img_t #將圖片存入batch張量中 batch.shape #輸出batch張量的shape |
torch.Size([100, 3, 256, 256])
進行前處理 (顏色數值正規化)
batch = batch.float() #將batch張量內的像素值轉換成浮點數 batch /= 255.0 #將像素值同除以255 #因為CNN網路需要調整 n_channels = batch.shape[1] #取得色彩通道的數量(batch張量的shape中,第1軸維度) for c in range(n_channels): #依次走訪每個色彩通道 mean = torch.mean(batch[:, c]) #計算平均值 std = torch.std(batch[:, c]) #計算標準差 batch[:, c] = (batch[:, c] - mean) / std #正規化的公式 # 轉換後的平均值=0、標準差=1 |
-
讀入"特殊格式"圖片資料
使用imageio模組
imageio.volread(資料夾路徑,檔案格式) : 讀入指定格式圖片
volumetric-dicom/2-LUNG 3.0 B70f-04083 資料夾中的 99張dcm檔
vol_arr = imageio.volread("./volumetric-dicom/2-LUNG 3.0 B70f-04083", 'DICOM') #讀取檔案,存放在vol_arr vol_arr.shape #輸出vol_arr的shape |
(99, 512, 512)
進行前處理 (維度調整 加入通道軸與深度軸)
張量名稱 = torch.unsqueeze(張量名稱, 要在"第幾軸"的位置插入一軸) : 插入一軸 原本第那軸(含)之後後挪
vol = torch.from_numpy(vol_arr).float() #先把資料轉成浮點數張量 vol = torch.unsqueeze(vol, 1) #在第"1"軸的位置增加插入一個通道軸,維度為1 vol = torch.unsqueeze(vol, 1) #在第"1"軸的位置增加插入一個深度軸,維度為1 vol.shape #增加維度 |
torch.Size([99, 1, 1, 512, 512])
-
使用csv模組 (搭配with開啟檔案)
with open(檔案路徑,"r") as 自訂名稱:
CSV格式檔案名稱=csv.reader(自訂名稱, delimiter=分割條件)
import csv with open("./tabular-wine/winequality-white.csv", 'r') as f: data = list(csv.reader(f, delimiter=";")) #轉成list |
以二維list儲存
也可以使用open() (不用搭配with)
csv.reader(open(檔案路徑), delimiter=分割條件)
import csv data = csv.reader(open("./tabular-wine/winequality-white.csv"), delimiter=";") #open()函數 col_list = next(data) #next()函數 回傳迭代器的下一個項目 |
使用 next(可迭代資料) 函數
->產生第一行 的list 存在col_list
col_list:
['fixed acidity',
'volatile acidity',
'citric acid',
'residual sugar',
'chlorides',
'free sulfur dioxide',
'total sulfur dioxide',
'density',
'pH',
'sulphates',
'alcohol',
'quality']
使用pandas模組
pd.read_csv(檔案路徑,delimiter=分割條件)
可以加入skiprows=1 跳過首行不讀 只讀數值資料 (之後要轉張量 張量只能放數值)
import pandas as pd df=pd.read_csv("./tabular-wine/winequality-white.csv",delimiter=";") #儲存成DataFrame |
以DataFrame儲存 記錄index、columns名稱
使用numpy模組
np.loadtxt(檔案路徑, dtype=np.float32,delimiter=分割條件, skiprows=1)
這邊加入skiprows=1 跳過首行不讀 只讀數值資料 (之後要轉張量 張量只能放數值)
import numpy as np wineq_numpy = np.loadtxt("./tabular-wine/winequality-white.csv", dtype=np.float32, delimiter=";", skiprows=1) #儲存成ndarray |
以ndarray儲存 skiprows=1跳過第一行 只記錄數值
進行前處理 (轉為張量、quality欄位與其他欄位拆開)
剛剛使用pandas套件DataFrame儲存的話 可以使用pop (結果torch.from_numpy連pandas也可以轉@@)
DataFrame名稱.values 取數值 (不取index 、 columns)
y=torch.from_numpy(df.pop("quality").values) #最後一行(品質分數)的資料 x=torch.from_numpy(df.values) #除了最後一行(品質分數)之外的所有資料 |
y是quality欄位 (作為輸出)
x是其他欄位 (作為輸入)
使用numpy套件ndarray儲存的話
target = wineq[:, -1] #選擇最後一行(品質分數)的資料 data = torch.from_numpy(wineq_numpy)[:, :-1] #選擇除了最後一行(品質分數)之外的所有資料 |
target是quality欄位 (作為輸出)
data是其他欄位 (作為輸入)
one-hot 編碼
使用 scatter_ 自動回傳本身
需要插入數據的張量名稱.scatter_(one-hot編碼在"插入數據的張量名稱"的哪個維度,要改的張量名稱,要填入的東西)
如果是 scatter 則不回傳本身
需要插入數據的張量名稱 = 需要插入數據的張量名稱._scatter(one-hot編碼在"插入數據的張量名稱"的哪個維度,要改的張量名稱,要填入的東西)
target是quality欄位 數值為0~9 進行one-hot編碼
scatter要求資料格式torch.int64
target=target.to(torch.int64) |
target.shape : [4898] 一維 4898項
故先建立target_onehot 張量 shape為[4898,10] 值均為0的張量,用來存放編碼結果
target_onehot = torch.zeros(target.shape[0], 10) #建立shape為[4898,10]、值均為0的張量,用來存放編碼結果 |
one-hot編碼
target_onehot.scatter_(1, target.unsqueeze(1), 1.0) #依target的內容進行編碼 #放在第1維(第0維是4898項), target增一維作為要改的張量, 填入1.0 |
target_onehot 第1000到1019項 :
(tensor([[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.]])
get_dummies 進行One Hot Encode
gender欄位直接分成兩行
data = pd.get_dummies(data) |
from tensorflow.keras.utils import to_categorical
to_categorical
tf.one_hot
label = tf.one_hot(label, NUM_CLASSES)
計算平均值
torch.mean(張量名稱, dim=0)
# dim等於axis 互通
計算標準差
torch.var(data, dim=0)
計算平方根
torch.sqrt(張量名稱)
數據標準化
data_mean = torch.mean(data, dim=0) #計算平均值 #dim=axis data_var = torch.var(data, dim=0) #計算標準差 data_normalized = (data - data_mean) / torch.sqrt(data_var) #用Python實現標準化的公式 |
-
轉置
張量名稱 = 張量名稱.permute(4,2,3,0,1) #裡面填入自訂軸順序
cf.
transpose
指定兩軸互換
align_as
.t() 二維轉置
.T 任意維度轉置 順序顛倒
-
使用Bool-Tensor找值
bad_data = data[target <= 3] #利用索引篩選出符合目標的項目 bad_data |
Bool-Series找值
-
比較
torch.lt #前者的資料<後者 True 反之 False
torch.lt(張量A,張量B) #可以挑出A中,值小於B的項目索引 回傳Bool-Tensor
-
張量名稱.dtype : 看資料型態
張量名稱[裡面可以放條件].sum(裡面可以放條件).item() : 可以看符合條件的項目數量的值加總
(裡面可以放條件).sum().item()
torch.sum(裡面可以放條件).sum().item() : 可以看符合條件的項目數量
np.loadtxt(檔案路徑,
dtype=資料格式,
comments=評論開始的字元或字元列表,
delimiter=分割條件,
converters=字典將列號對映到一個函式,該函式將把列的字串解析成所需的值,
usecols=要讀取的列索引,
unpack=是否對返回的陣列進行轉置,
ndmin=返回陣列的最小維數,
encoding=編碼方式,
skiprows=跳過前幾行,
max_rows=讀取 skiprows 行後的最大行數)
np.genfromtxt(檔案路徑,
dtype=資料格式,
comments=註釋標示符號,自動忽略註釋標是符號後面的字串
delimiter=分割條件,
converters=字典或lambda函數,將一種數據格式化成另一種數據格式,
usecols=要讀取的列索引,
unpack=是否對返回的陣列進行轉置,
ndmin=返回陣列的最小維數,
missing_values=視為遺失的值
filling_values=替代遺失的值
encoding=編碼方式,
skip_header=跳過前幾行,
skip_footer=跳過後幾行)
bikes_numpy = np.loadtxt("./bike-sharing-dataset/hour-fixed.csv", #資料集所在路徑 dtype=np.float32, delimiter=",", skiprows=1, converters={1: lambda x: float(x[8:10])}) |
converters={1: lambda x: float(x[8:10])}
1代表 處理第一直行
把其內容當作字串輸入 取字串中的第8到9個字元集合起來轉浮點數當作輸出
hour-fixed.csv檔案中 第1行是"dteday"資料
2012/11/24
2011/1/1
x[0:4] -> 第0~3個字元 2012 2011
第4個字元 /
x[5:7] -> 第5或第5~6個字元 1~12
第6或7個字元 /
x[8:10] -> 第7或第8~9個字元 1~31
= = 這超奇怪的 關於 / 他怎麼認知我搞不懂
另外
他是用字串作為讀入
關於這x
x[填第幾個] 跟 x[填區段] 有差別
這邊出來是第0直行每個字串中第4個字元轉浮點數
np.loadtxt("./test.csv", converters={0: lambda x: float(x[4:5])}) |
這邊出來是第0直行每個字串中第4個字元轉浮點數
np.loadtxt("./test.csv", converters={0: lambda x: float(x[4])}) |
這邊出來是第0直行每個字串中第4個字元的ASCII碼轉浮點數
所以如果不想使用區段就必須再轉回去
np.loadtxt("./test.csv", converters={0: lambda x: float(chr(x[4]))}) |
-
view
類似轉置 類似reshape
但原理是:
將一個連續的張量攤平(1維)再重組成要的格式
所以需要填入的是連續的張量,輸出的也是連續的張量
裡面數字可以填-1 自動計算對應數值
a=torch.randn(4,5,6) a.T.contiguous().view(5,8,-1).is_contiguous() |
a張量 4*5*6
.T -> 轉置 變成不連續
.contiguous() -> 強制轉為連續張量
.view(5,8,-1) -> 變成連續張量 5*8*3 (3自動計算)
.is_contiguous() -> 是否是連續張量
True
-
單字進行one-hot 編碼
讀檔
with open('./1342-0.txt', encoding='utf-8-sig') as f: text = f.read() |
拆字
words_in_book = [word.strip('.,;:"!?”“_-[]#*') for word in text.lower().split()] |
建立字典
words_in_book_dict = {word: i for (i, word) in enumerate(sorted(set(words_in_book)))} #key為單字,value為其編碼(就是該單字在單字串列中的索引) |
使用字典 對檔案單字進行one-hot
words_onehot = torch.zeros(len(words_in_book), len(words_in_book_dict)) #創建一個張量,用來儲存編碼後的單字向量 for i, word in enumerate(words_in_book): words_index = words_in_book_dict[word] words_onehot[i][words_index] = 1 |
words_onehot.shape
torch.Size([124592, 7256])
總共有124592個單字、字典紀載7256個單字
words_onehot
tensor([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]])
words_in_book_dict['impossible']
3390
impossible單字的編號是3390
list(word2index_dict.keys())[list(word2index_dict.values()).index(3390)]
'impossible'
編號3390的單字是impossible