趣游—LSTM

import random

import pandas as pd
import torch
import torch.nn as nn
import torchvision.transforms as transforms
import torchvision.datasets as dsets
import xlrd
from torch.autograd import Variable
import numpy as np
import json
'''
STEP 1: LOADING DATASET 读json文件
'''
#导入初始用户特征的表格
data=xlrd.open_workbook("D:/PCstudy/data/Question_reults_end.xls")
table = data.sheets()[0]#选择第0张表
nrows = table.nrows  # 行数
ncols = table.ncols  # 列数
datamatrix = [] # 构造列表
for i in range(nrows):
        rows = table.row_values(i) #获取第i行的内容
        datamatrix.append(rows)  #写入数据

# 构造用户特征数据
users = {}# 包括是否去过景点、年龄、性别、收入、城市、学历、职业
vis = [] # 是否去过景点
age = [] # 年龄
sex = [] # 性别
income = [] # 收入
citys = [] # 城市
school = [] # 学历
wokers = [] # 职业
for i in range(nrows):
    if i == 0:
        continue
    vis.append(datamatrix[i][0])
    age.append(datamatrix[i][1])
    sex.append(datamatrix[i][2])
    income.append(datamatrix[i][3])
    citys.append(datamatrix[i][4])
    school.append(datamatrix[i][22])
    wokers.append(datamatrix[i][23])

# 转换成pandas
dfresult= pd.DataFrame()
dfPclass = pd.get_dummies(vis)
dfPclass.columns = ['vis_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)
dfPclass = pd.get_dummies(age)
dfPclass.columns = ['age_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)
dfPclass = pd.get_dummies(sex)
dfPclass.columns = ['sex_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)
dfPclass = pd.get_dummies(income)
dfPclass.columns = ['income_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)
dfPclass = pd.get_dummies(citys)
dfPclass.columns = ['citys_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)
dfPclass = pd.get_dummies(school)
dfPclass.columns = ['school_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)
dfPclass = pd.get_dummies(wokers)
dfPclass.columns = ['wokers_' + str(x) for x in dfPclass.columns]
dfresult = pd.concat([dfresult, dfPclass], axis=1)

users = dfresult.values
#print(dfresult)

#当前用户特征,labels=output是当前真实的POI
user = 0
poi = 0

'''
--- 读取json数据,读取用户的游玩数据 ---
对于一个batch,有n个数据,每个数据是(P1,P2,P3,...Pk),Pk是17个POI数组

'''

def one_batch(x):  # 选取前x个数据
    in_num = []  # 输入
    out_num = []  # 输出
    for y in range(64):  # 每次随机选取64个用户
        size = 0
        while size < x+2:
            i = random.randint(1, 89)  # 范围[1,89]
            path = "D:/PCstudy/pythonProject1/routing/user_data/user_visit_json"
            path += str(i)
            path += ".json"
            # 读取文件数据
            with open(path, "r") as f:
                row_data = json.load(f)

            # 第i个用户的第j个走法
            j = random.randint(1, 100)
            j = str(j)
            list = row_data[j]['visit_historal']
            list = np.array(list)
            size = np.size(list)
        #print("size = ",size)
        #print("x = ",x)
        #print("游客特征数据:")
        #print(users[i-1])
        user_i = np.array(users[i-1]) # 当前用户特征
        user_i = user_i.tolist()
        #print(user_i)
        #print(row_data[j])
        # 选取第j个走法的前x个点
        k = row_data[j]['visit_historal'][x] #当前所在景点
        POW_k = row_data[j]['POW_history'][x] #当前体力值POW
        b = []
        b.append(k)
        b.append(POW_k)
        POI_list = []  # 当前经历的历史POI
        #print(x)
        for w in range(x+1):
            #print(w)
            POI_w = row_data[j]['POI_historal'][w]
            POI_w = POI_w + user_i + b  # 所有用户特征(POI-17 + 用户特征32 + 2(当前景点 + 当前体力值)) = 51
            POI_list.append(POI_w)
            # print(POI_w)
        in_num.append(POI_list)
        out_num.append(row_data[j]['POI_historal'][x+1])
        #print(row_data[j]['POI_historal'][x+1])
    in_num = np.float32(in_num)
    in_num = torch.from_numpy(in_num)
    out_num = np.float32(out_num)
    out_num = torch.from_numpy(out_num)
    return (in_num,out_num)

'''
STEP 2: MAKING DATASET ITERABLE
'''
# 输入:用户特征(特征+当前体力值+上一次的POI)+ 当前前位置  类型:Tensor  三维:batch_size + 整体形状
# 64 * (70 * 10) * 17
# 输出:17个景点的预测POI
batch_size = 64  #批量大小

num_epochs = 10  #自己设定,训练轮次
num_epochs = int(num_epochs)

'''
STEP 3: CREATE MODEL CLASS
'''


class LSTMModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
        super(LSTMModel, self).__init__()
        # Hidden dimensions
        self.hidden_dim = hidden_dim

        # Number of hidden layers
        self.layer_dim = layer_dim

        # Building your LSTM
        # batch_first=True causes input/output tensors to be of shape
        # (batch_dim, seq_dim, feature_dim)
        self.lstm = nn.LSTM(input_dim, hidden_dim, layer_dim, batch_first=True)

        # Readout layer
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        # Initialize hidden state with zeros
        #######################
        #  USE GPU FOR MODEL  #
        #######################
        if torch.cuda.is_available():
            h0 = Variable(torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).cuda())
        else:
            h0 = Variable(torch.zeros(self.layer_dim, x.size(0), self.hidden_dim))

        # Initialize cell state
        if torch.cuda.is_available():
            c0 = Variable(torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).cuda())
        else:
            c0 = Variable(torch.zeros(self.layer_dim, x.size(0), self.hidden_dim))

        # One time step
        out, (hn, cn) = self.lstm(x, (h0, c0))

        # Index hidden state of last time step
        # out.size() --> 100, 28, 100
        # out[:, -1, :] --> 100, 100 --> just want last time step hidden states!
        out = self.fc(out[:, -1, :])
        # out.size() --> 100, 10
        return out
'''
STEP 4: INSTANTIATE MODEL CLASS
'''
input_dim = 51  #输入维度
hidden_dim = 100 #隐藏节点个数
layer_dim = 3  # ONLY CHANGE IS HERE FROM ONE LAYER TO TWO LAYER
output_dim = 17 #输出维度

model = LSTMModel(input_dim, hidden_dim, layer_dim, output_dim)

#######################
#  USE GPU FOR MODEL  #
#######################

if torch.cuda.is_available():
    model.cuda()

'''
STEP 5: INSTANTIATE LOSS CLASS
'''
criterion = torch.nn.MSELoss()

'''
STEP 6: INSTANTIATE OPTIMIZER CLASS
'''
learning_rate = 0.1

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

'''
STEP 7: TRAIN THE MODEL
'''

# Number of steps to unroll
seq_dim = 0

iter = 0
for epoch in range(num_epochs):
    for i in range(64): #images=input是当前用户特征, labels=output是当前真实的POI
        x = random.randint(0, 7)
        seq_dim = x+1
        #print(x)
        (images, labels) = one_batch(x)
        # Load images as Variable
        #######################
        #  USE GPU FOR MODEL  #
        #######################
        #print(seq_dim)
        if torch.cuda.is_available():
            images = Variable(images.view(-1, seq_dim, input_dim).cuda())
            labels = Variable(labels.cuda())
        else:
            images = Variable(images.view(-1, seq_dim, input_dim))
            labels = Variable(labels)

        # Clear gradients w.r.t. parameters
        optimizer.zero_grad()

        # Forward pass to get output/logits
        # outputs.size() --> 100, 10
        print(np.shape(images))
        outputs = model(images)

        # Calculate Loss: softmax --> cross entropy loss
        loss = criterion(outputs, labels)

        # Getting gradients w.r.t. parameters
        loss.backward()

        # Updating parameters
        optimizer.step()

        iter += 1

        if iter % 500 == 0:
            # Calculate Accuracy
            correct = 0
            total = 0
            # Iterate through test dataset
            #——————测试——————
            test_loader = one_batch(x)
            for images, labels in test_loader:
                #######################
                #  USE GPU FOR MODEL  #
                #######################
                if torch.cuda.is_available():
                    images = Variable(images.view(-1, seq_dim, input_dim).cuda())
                else:
                    images = Variable(images.view(-1, seq_dim, input_dim))

                # Forward pass only to get logits/output
                outputs = model(images)

                # Get predictions from the maximum value
                _, predicted = torch.max(outputs.data, 1)

                # Total number of labels
                total += labels.size(0)

                # Total correct predictions
                #######################
                #  USE GPU FOR MODEL  #
                #######################
                if torch.cuda.is_available():
                    correct += (predicted.cpu() == labels.cpu()).sum()
                else:
                    correct += (predicted == labels).sum()

            accuracy = 100 * correct / total
            if accuracy >=0.8:
                torch.save(LSTMModel.state_dict(), "lstmdata.para")  #保存lstm参数

            # Print Loss
            print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.data[0], accuracy))

# 将训练好的参数加载到模型
anser = LSTMModel()
anser.load_state_dict(torch.load("lstmdata.para"))

#测试


你可能感兴趣的:(机器学习,lstm,python)