【Pytorch神经网络实战案例】07 预测泰坦尼克号上生存的乘客
生活随笔
收集整理的這篇文章主要介紹了
【Pytorch神经网络实战案例】07 预测泰坦尼克号上生存的乘客
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 樣本處理
1.1 載入樣本代碼---Titanic forecast.py(第1部分)
import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from scipy import stats import pandas as pd import matplotlib.pyplot as plt import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"def moving_average(a, w=10):#定義函數計算移動平均損失值if len(a) < w:return a[:]return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]def plot_losses(losses):avgloss= moving_average(losses) #獲得損失值的移動平均值plt.figure(1)plt.subplot(211)plt.plot(range(len(avgloss)), avgloss, 'b--')plt.xlabel('step number')plt.ylabel('Training loss')plt.title('step number vs. Training loss')plt.show()###1.1 載入樣本 titanic_data = pd.read_csv('csv_list/titanic3.csv') print(titanic_data.columns) # 輸出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket','fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest'],dtype='object')1.2 離散數據
1.2.1 離散數據的特征
數據之間沒有任何連續性的數據稱為離散數據,例如數據中的男、女。
離散數據通常可以處理為one-hot編碼或者詞向量,可以分為兩類:
①具有固定類別的樣本(性別):易于處理,按照總得類別進行變換
②沒有固定類別的樣本(姓名):通過hash算法或其他散列算法處理,再通過詞向量技術進行轉化
1.2.2 連續數據的特征
數據之間具有連續性的數據,稱為連續數據,例如票價與年齡
對于連續數據做特征變化時,通過對數運算or歸一化處理,使其具有統一的值域
1.2.3 連續數據與離散數據的轉化
對于一個跨度很大的特征屬性進行數據預處理時,可以有三種方法:
①按照最大值、最小值進行歸一化處理
②使用對數運算
③按照分布情況將其分為幾類,再做離散化處理
1.3 處理樣本中的離散數據與NAn值
1.3.1 將離散數據轉化為one-hot編碼 代碼---Titanic forecast.py(第2部分)
###1.2 處理樣本中的離散數據與Nan值 # 將離散數據的字段轉化為one-hot # get_dummies()會根據指定列中的離散值轉化為one-hot編碼,并將轉化后所生成的新列放到原有數據的后面,在新的列中的數據用0,1來表示是否具有該列的屬性。 titanic_data = pd.concat([titanic_data,pd.get_dummies(titanic_data['sex']),pd.get_dummies(titanic_data['embarked'],prefix="embark"),pd.get_dummies(titanic_data['pclass'],prefix="class")],axis=1 ) print(titanic_data.columns) # 輸出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket', 'fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest', 'female', 'male', 'embark_C', 'embark_Q', 'embark_S', 'class_1', 'class_2','class_3'],dtype='object') print(titanic_data['sex']) print(titanic_data['female']) # 在sex列中,值為female的行,在female列中值為11.3.2 對數據中的Nan值進行過濾填充代碼---Titanic forecast.py(第3部分)
對于兩個具有連續屬性的數據列進行Nan值處理,age與fare。
# 對Nan值進行過濾填充 # 調用fillna()對特定列的NAn值進行過濾,并用該列的平均值進行填充 titanic_data["age"] = titanic_data["age"].fillna(titanic_data["age"].mean()) # 乘客年齡 titanic_data["fare"] = titanic_data["fare"].fillna(titanic_data["fare"].mean()) # 乘客票價1.3.3 剔除無用的數據列代碼---Titanic forecast.py(第4部分)
本部分剔除與遇難無關的數據列。
## 去除與是否獲取無關的數據列 titanic_data = titanic_data.drop(['name','ticket','cabin','boat','body','home.dest','sex','embarked','pclass'], axis=1) print(titanic_data.columns ) # 輸出真正需要處理的數據列1.4 分離樣本與標簽并制作數據集代碼---Titanic forecast.py(第5部分)
將suivived列從數據集中抽取出來,將數據列中剩下的數據作為輸入樣本。
### 1.3 分離樣本和標簽并制作數據集 # 分離樣本 labels = titanic_data["survived"].to_numpy()titanic_data = titanic_data.drop(['survived'],axis=1) data = titanic_data.to_numpy()# 樣本屬性名稱 feature_names = list(titanic_data.columns)# 將樣本分為訓練和測試兩部分 np.random.seed(10) # 設置隨機種子,保證每次運行所分的樣本一致# set() 函數創建一個無序不重復元素集,x-y返回一個新的集合,包括在集合x中但不在集合y中的元素 # random.choice(a=5, size=3, replace=False, p=None) 參數意思分別 是從a中以概率P隨機選擇3個, p沒有指定的時候相當于是一致的分布 # 按照行號提取 train_indices = np.random.choice(len(labels),int(0.7 * len(labels)),replace = False) print('train_indices++++',train_indices) test_indices = list(set(range(len(labels))) - set(train_indices)) #將剩余部分設為測試集 print('train_indices++++',train_indices)# data[:]相當于重新拷貝一個列表,列表是可變對象如果直接引用傳參給函數,則會導致修改其中任意一個變量,其余變量相應改變。但是,通過這種方式可以避免這種情況。 train_features = data[train_indices] train_labels = labels[train_indices]test_features = data[test_indices] test_labels = labels[test_indices] print('測試樣本數量',len(test_labels)) # 測試樣本數量 3932 訓練模型
2.1 定義Mish激活函數與多層全連接網絡代碼---Titanic forecast.py(第6部分)
###定義Mish激活函數與多層全連接網絡 # 定一個帶有3層全連接網絡的類,每個網絡層使用Mish作為激活函數,該模型使用交叉熵損失函數 class Mish(nn.Module):def __init__(self):super().__init__()def forward(self,x):x = x * (torch.tanh(F.softplus(x)))return xtorch.manual_seed(0) # 設置隨機種子函數class ThreeLinearModel(nn.Module):def __init__(self):super().__init__()self.linear1 = nn.Linear(12,12)self.mish1 = Mish()self.linear2 = nn.Linear(12,8)self.mish2 = Mish()self.linear3 = nn.Linear(8,2)self.softmax = nn.Softmax(dim = 1)self.criterion = nn.CrossEntropyLoss() #定義交叉熵def forward(self,x): # 定義一個全連接網絡lin1_out = self.linear1(x)out_1 = self.mish1(lin1_out)out_2 = self.mish2(self.linear2(out_1))return self.softmax(self.linear3(out_2))def getloss(self,x,y): # 實現類的損失值計算接口y_pred = self.forward(x)loss = self.criterion(y_pred,y)return loss2.2 訓練模型并輸出結果代碼---Titanic forecast.py(第7部分)
### 訓練模型并輸出結果 if __name__ == '__main__':net = ThreeLinearModel()num_epochs = 200optimizer = torch.optim.Adam(net.parameters(),lr = 0.04)# 將輸入的樣本標簽轉化為標量input_tensor = torch.from_numpy(train_features).type(torch.FloatTensor)label_tensor = torch.from_numpy(train_labels)losses = [] # 定義損失值列表for epoch in range(num_epochs):loss = net.getloss(input_tensor, label_tensor)losses.append(loss.item())optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數if epoch % 20 == 0:print('Epoch {}/{} => Loss: {:.2f}'.format(epoch + 1, num_epochs, loss.item()))os.makedirs('models', exist_ok=True)torch.save(net.state_dict(), 'models/titanic_model.pt')plot_losses(losses)# 輸出訓練結果# tensor.detach():從計算圖中脫離出來,返回一個新的tensor,新的tensor和原tensor共享數據內存,(這也就意味著修改一個tensor的值,另外一個也會改變),# 但是不涉及梯度計算。在從tensor轉換成為numpy的時候,如果轉換前面的tensor在計算圖里面(requires_grad = True),那么這個時候只能先進行detach操作才能轉換成為numpyout_probs = net(input_tensor).detach().numpy()out_classes = np.argmax(out_probs, axis=1)print("Train Accuracy:", sum(out_classes == train_labels) / len(train_labels))# 測試模型test_input_tensor = torch.from_numpy(test_features).type(torch.FloatTensor)out_probs = net(test_input_tensor).detach().numpy()out_classes = np.argmax(out_probs, axis=1)print("Test Accuracy:", sum(out_classes == test_labels) / len(test_labels))3.0 代碼匯總
import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from scipy import stats import pandas as pd import matplotlib.pyplot as plt import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"def moving_average(a, w=10):#定義函數計算移動平均損失值if len(a) < w:return a[:]return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]def plot_losses(losses):avgloss= moving_average(losses) #獲得損失值的移動平均值plt.figure(1)plt.subplot(211)plt.plot(range(len(avgloss)), avgloss, 'b--')plt.xlabel('step number')plt.ylabel('Training loss')plt.title('step number vs. Training loss')plt.show()###1.1 載入樣本 titanic_data = pd.read_csv('csv_list/titanic3.csv') print(titanic_data.columns) # 輸出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket','fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest'],dtype='object')###1.2 處理樣本中的離散數據與Nan值 # 將離散數據的字段轉化為one-hot # get_dummies()會根據指定列中的離散值轉化為one-hot編碼,并將轉化后所生成的新列放到原有數據的后面,在新的列中的數據用0,1來表示是否具有該列的屬性。 titanic_data = pd.concat([titanic_data,pd.get_dummies(titanic_data['sex']),pd.get_dummies(titanic_data['embarked'],prefix="embark"),pd.get_dummies(titanic_data['pclass'],prefix="class")],axis=1 ) print(titanic_data.columns) # 輸出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket', 'fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest', 'female', 'male', 'embark_C', 'embark_Q', 'embark_S', 'class_1', 'class_2','class_3'],dtype='object') print(titanic_data['sex']) print(titanic_data['female']) # 在sex列中,值為female的行,在female列中值為1 # 對Nan值進行過濾填充 # 調用fillna()對特定列的NAn值進行過濾,并用該列的平均值進行填充 titanic_data["age"] = titanic_data["age"].fillna(titanic_data["age"].mean()) # 乘客年齡 titanic_data["fare"] = titanic_data["fare"].fillna(titanic_data["fare"].mean()) # 乘客票價## 去除與是否獲取無關的數據列 titanic_data = titanic_data.drop(['name','ticket','cabin','boat','body','home.dest','sex','embarked','pclass'], axis=1) print(titanic_data.columns )### 1.3 分離樣本和標簽并制作數據集 # 分離樣本 labels = titanic_data["survived"].to_numpy()titanic_data = titanic_data.drop(['survived'],axis=1) data = titanic_data.to_numpy()# 樣本屬性名稱 feature_names = list(titanic_data.columns)# 將樣本分為訓練和測試兩部分 np.random.seed(10) # 設置隨機種子,保證每次運行所分的樣本一致# set() 函數創建一個無序不重復元素集,x-y返回一個新的集合,包括在集合x中但不在集合y中的元素 # random.choice(a=5, size=3, replace=False, p=None) 參數意思分別 是從a中以概率P隨機選擇3個, p沒有指定的時候相當于是一致的分布 # 按照行號提取 train_indices = np.random.choice(len(labels),int(0.7 * len(labels)),replace = False) print('train_indices++++',train_indices) test_indices = list(set(range(len(labels))) - set(train_indices)) #將剩余部分設為測試集 print('train_indices++++',train_indices)# data[:]相當于重新拷貝一個列表,列表是可變對象如果直接引用傳參給函數,則會導致修改其中任意一個變量,其余變量相應改變。但是,通過這種方式可以避免這種情況。 train_features = data[train_indices] train_labels = labels[train_indices]test_features = data[test_indices] test_labels = labels[test_indices] print('測試樣本數量',len(test_labels)) # 測試樣本數量 393###定義Mish激活函數與多層全連接網絡 # 定一個帶有3層全連接網絡的類,每個網絡層使用Mish作為激活函數,該模型使用交叉熵損失函數 class Mish(nn.Module):def __init__(self):super().__init__()def forward(self,x):x = x * (torch.tanh(F.softplus(x)))return xtorch.manual_seed(0) # 設置隨機種子函數class ThreeLinearModel(nn.Module):def __init__(self):super().__init__()self.linear1 = nn.Linear(12,12)self.mish1 = Mish()self.linear2 = nn.Linear(12,8)self.mish2 = Mish()self.linear3 = nn.Linear(8,2)self.softmax = nn.Softmax(dim = 1)self.criterion = nn.CrossEntropyLoss() #定義交叉熵def forward(self,x): # 定義一個全連接網絡lin1_out = self.linear1(x)out_1 = self.mish1(lin1_out)out_2 = self.mish2(self.linear2(out_1))return self.softmax(self.linear3(out_2))def getloss(self,x,y): # 實現類的損失值計算接口y_pred = self.forward(x)loss = self.criterion(y_pred,y)return loss### 訓練模型并輸出結果 if __name__ == '__main__':net = ThreeLinearModel()num_epochs = 200optimizer = torch.optim.Adam(net.parameters(),lr = 0.04)# 將輸入的樣本標簽轉化為標量input_tensor = torch.from_numpy(train_features).type(torch.FloatTensor)label_tensor = torch.from_numpy(train_labels)losses = [] # 定義損失值列表for epoch in range(num_epochs):loss = net.getloss(input_tensor, label_tensor)losses.append(loss.item())optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數if epoch % 20 == 0:print('Epoch {}/{} => Loss: {:.2f}'.format(epoch + 1, num_epochs, loss.item()))os.makedirs('models', exist_ok=True)torch.save(net.state_dict(), 'models/titanic_model.pt')plot_losses(losses)# 輸出訓練結果# tensor.detach():從計算圖中脫離出來,返回一個新的tensor,新的tensor和原tensor共享數據內存,(這也就意味著修改一個tensor的值,另外一個也會改變),# 但是不涉及梯度計算。在從tensor轉換成為numpy的時候,如果轉換前面的tensor在計算圖里面(requires_grad = True),那么這個時候只能先進行detach操作才能轉換成為numpyout_probs = net(input_tensor).detach().numpy()out_classes = np.argmax(out_probs, axis=1)print("Train Accuracy:", sum(out_classes == train_labels) / len(train_labels))# 測試模型test_input_tensor = torch.from_numpy(test_features).type(torch.FloatTensor)out_probs = net(test_input_tensor).detach().numpy()out_classes = np.argmax(out_probs, axis=1)print("Test Accuracy:", sum(out_classes == test_labels) / len(test_labels))總結
以上是生活随笔為你收集整理的【Pytorch神经网络实战案例】07 预测泰坦尼克号上生存的乘客的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智慧交通day02-车流量检测实现05:
- 下一篇: 动态规划思路和Python解决零钱兑换问