廢廢吸取了昨天的教訓,改換方法。
今天將資料分成的x.csv(牌局資料)與y.csv(label),先寫入train.csv的header(label、1x1x1、1x1x2),如下:
再將x.csv的15個column轉成二維並插入新的陣列變成深度為15且17x17大小的三維矩陣,轉換好後攤平成一維陣列並且在前面插入label後寫入train.csv。
#整合前面零散的code
import random
import numpy as np
import numpy as reshape
import csv
"""把data & label連在一起並且轉成CNN圖片格式寫入train.csv"""
x=[]
y=[]
size = np.array([[0]*17]*17) #二維資料
rrow=[]
roww=[]
all = []
print("reading file...")
with open('test_x.csv', newline='') as csvfile:
# 讀取 CSV 檔內容,將每一列轉成一個 dictionary
#rows = csv.DictReader(csvfile) #csv.DictReader可以資料查找 d = {key1: value1, key2: value2}
rows = csv.reader(csvfile)
data_list = list(rows)
with open('test_y.csv', newline='') as file:
# 讀取 CSV 檔內容,將每一列轉成一個 dictionary
#rows = csv.DictReader(csvfile) #csv.DictReader可以資料查找 d = {key1: value1, key2: value2}
rows = csv.reader(file)
data_list_y = list(rows)
print("list insert to array...")
for a in range(len(data_list)):
x.append(data_list[a])
x=np.array(x)
for a in range(len(data_list_y)):
y.append(data_list_y[a])
print("create train.csv...")
file = open('train.csv',mode='w', newline='')
writer = csv.writer(file)
headers = ['label']
for a in range(15):
for b in range(17):
for c in range(17):
headers.append(str(a+1)+'x'+str(b+1)+'x'+str(c+1))
writer.writerow(headers)
print("start convert to 3D-array...")
for b in range(len(x)):
for c in range(15):
if c == 9 or c == 10:
x[b,c]=float(x[b,c])
else:
x[b,c]=int(x[b,c])
for i in range(len(x)):
for j in range(15):
if j >= 1 and j <=7 : #放撲克編碼
if int(x[i,j]) == -1:
size[random.randrange(0,16,1),random.randrange(0,16,1)] = 0
else:
suit=int(x[i,j]) % 4
rank=int(x[i,j]) // 4
size[suit,rank] = 1
else:
if j==9:#小數籌碼
size[6, 0] = float(x[i,j])
elif j==10:
size[7, 1] = float(x[i,j])
else:
if int(x[i,j]) == -1:
size[random.randrange(0,16,1),random.randrange(0,16,1)] = 0
else:
if j==0:
size[4, int(x[i,j])] = int(x[i,j])
elif j==8:
size[5, int(x[i,j])] = int(x[i,j])
else:
size[j, int(x[i,j])] = int(x[i,j])
for k in range(17):
all.append(size[k,])
rrow.extend(size[k,])
size = np.array([[0]*17]*17) #二維資料
y[i].extend(rrow)
writer.writerow(y[i])
rrow=[]
file.close()
all = np.array(all)
all = all.reshape(len(x),15,17,17)
print('维数:',all.shape)
開始執行CNN並且儲存模型,這邊為了能快點執行只用了10筆資料進行測試,程式碼參考了這兩個網站:
【以100張圖理解 Neural Network -- 觀念與實踐系列 第 7 篇】
【使用自己的csv文件數據進行神經網絡學習時的數據處理】
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
# 用來後續將 label 標籤轉為 one-hot-encoding
from keras.utils import np_utils
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
import pandas as pd
dataset=pd.read_csv('train.csv')#文件读取
dataset = dataset.values#去掉標頭
#train.csv第一列为数字类别标签,后面所有列均为像素值,故一共785列(784+1)
data = np.array(dataset[:,:-1]) #从第二列开始读取为训练数据
label = np.array(dataset[:,0:1]) #读取第一列为数字类别标签
data = np.reshape(data, (-1,17,17,15)) #更改为网络输入类型,即原始图像shape(28*28*1)
train_data,test_data,train_label,test_label = train_test_split(data,label,test_size=0.2)
#按照8:2划分训练集和验证集
# 將 training 的 label 進行 one-hot encoding,例如數字 7 經過 One-hot encoding 轉換後是 array([0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], dtype=float32),即第7個值為 1
train_label_onehot = np_utils.to_categorical(train_label)
test_label_onehot = np_utils.to_categorical(test_label)
# 將 training 的 input 資料轉為 28*28 的 2維陣列
# training 與 testing 資料數量分別是 60000 與 10000 筆
# train_data_2D 是 [60000, 28*28] 的 2維陣列
train_data_2D = train_data.reshape(8, 15*17*17).astype('float32')
test_data_2D = test_data.reshape(2, 15*17*17).astype('float32')
train_data_norm = train_data_2D/255
test_data_norm = test_data_2D/255
# 建立簡單的線性執行的模型
model = Sequential()
# Add Input layer, 隱藏層(hidden layer) 有 256個輸出變數
model.add(Dense(units=256, input_dim=4335, kernel_initializer='normal', activation='relu'))
# Add output layer
model.add(Dense(units=5, kernel_initializer='normal', activation='softmax'))
# 編譯: 選擇損失函數、優化方法及成效衡量方式
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
# 進行 model 訓練, 訓練過程會存在 train_history 變數中
# 將 60000 張 training set 的圖片,用 80% (48000張) 訓練模型,用 20% (12000張) 驗證結果
# epochs 10 次,就是訓練做了 10 次
# batch_size 是 number of samples per gradient update,每一次進行 gradient descent 使用幾個 samples
# verbose 是 train_history 的 log 顯示模式,2 表示每一輪訓練,列印一行 log
train_history = model.fit(x=train_data_norm, y=train_label_onehot, validation_split=0.2, epochs=10, batch_size=64, verbose=2)
# 用 10000 筆測試資料,評估訓練後 model 的成果(分數)
scores = model.evaluate(test_data_norm, test_label_onehot)
print()
print("Accuracy of testing data = {:2.1f}%".format(scores[1]*100.0))
# 預測(prediction)
print(test_data_norm)
X = test_data_norm[0:10,:]
print("X: ", X)
predictions = model.predict(X)
# get prediction result
predict = np.argmax(predictions,1)
print("predict: ",predict)
# 模型訓練結果 結構存檔
from keras.models import model_from_json
json_string = model.to_json()
with open("model.config", "w") as text_file:
text_file.write(json_string)
# 模型訓練結果 權重存檔
model.save_weights("model.weight")
# 顯示 第一筆訓練資料的圖形,確認是否正確
#plt.imshow(train_data[0])
#plt.show()
#plt.imsave('1.png', train_data[0])
plt.clf()
plt.plot(train_history.history['loss'])
plt.plot(train_history.history['val_loss'])
plt.title('Train History')
plt.ylabel('loss')
plt.xlabel('Epoch')
plt.legend(['loss', 'val_loss'], loc='upper left')
#plt.show()
plt.savefig('loss.png')
接下來廢廢預計輸入測試用資料來進行預測,以上記錄到此明天見吧各位!