Tensorflow RNN 預測美國綠卡排期

由於美國發放綠卡對每個國家有名額限制。所以對於申請綠卡的人數多的國家,比如中國,印度,就有了綠卡排期。

每個月初,移民局會公布下個月的綠卡排期,如果你的Priority Date (優先日)在公布的排期之前,就可以申請了。但是排期不一定每個月都前進,有時候會止步不前,有時候甚至會倒退。

所以這裡我們用遞歸神經網路(RNN),來預測下個月排期是否前進,這裡我們預測的是EB3-China,對於其他類型的綠卡排期,EB2, EB5, 親屬移民也都是同樣的道理。

數據

首先我們需要獲取排期的歷史數據,在圖表中選擇EB3-China, 日期選擇最近十年的數據從2007年開始

選好後,複製下面的表格,保存起來,我們先把Wait Time, 轉化成具體的天數。可以用這段code (為了方便,假設一年365天,一個月30天)。用這個月的Wait Time和上個月相比,少於30天,那麼這個月綠卡排期就前進了,反之就後退了。比如十一月Wait Time, 100 天,十二月125 天,(100 + 30 - 125) > 0,代表排期前進了五天

經過處理,得到training data (只需要裡面的advance 列),下圖裡面1代表前進,0代表後退,或者沒有變化

2007-2017 EB3 前進後退情況

RNN 模型需要一個序列,所以我們往前看N個月的前進後退情況,來預測這個月的前進後退情況,這裡選擇了N=24, 也就是看過去兩年的情況,最後的序列應該是類似這個形狀 [[0], [1], [0]....[0], [1]]

# 過去24個月的結果sequence_length = 24df = pd.read_csv("data/pd_data.csv")advance = df[advance].apply(lambda x: float(x == True)).tolist()data = [] # input data, 過去24個月的結果data_output = [] # 當前月的結果for i in range(sequence_length, len(advance)): a = [] for s in advance[i-sequence_length:i]: a.append([s]) data.append(a) if advance[i] == 0: # 結果有兩種看情況,[1, 0], [0, 1] 如果沒有前進,就是[1, 0] data_output.append([1.0, 0.0]) else: # 如果前進是 [0, 1] data_output.append([0.0, 1.0])

RNN 模型

  • 輸入 Input, sequence_length = 24個月,一共有n條數據, 為了方便placeholder 裡面的條數 用None 表示代表任意size,所以輸入 尺寸是 n * sequence_length * 1,最後的1, 代表前進還是後退,只有兩種可能 [0], [1]。為什麼不能是 n * sequence_length? 因為Tensorflow dynamic_rnn 要求input 至少是 3維的(rank 3)

inputs = tf.placeholder(tf.float64, [None, sequence_length, 1])

  • 輸出 Output,輸出的維度是 n * 2, n 代表n 個數據,和input 裡面的n 相同,為什麼output size 不能是 n * 1, 或者直接是n? 因為之後計算loss/cost 要用到cross entropy,這樣比較方便。

# 只有前進或者後退兩種可能num_classes = 2targets = tf.placeholder(tf.float64, [None, num_classes])

  • Cell, 選用 GRUCell或者LSTM , GRU cell 初始化 只需要一個參數, hidden size, 就是圖片裡面ht的尺寸

hidden_size = 32 # number of hidden state, when the cell outputs, the number of statescell = tf.nn.rnn_cell.GRUCell(hidden_size)

  • 網路 RNN Network,通過dynamic_rnn 或者static_RNN 建立RNN 網路,因為我們所有的序列 都是固定長度24的, dynamic_rrn 返回兩個值, outputs, 和last_states, last_states 我們不太關心,outputs的形狀是[batch_size, max_time, cell_state_size],我們需要的是最後時刻的輸出, 所以reshape/ transpose outputs成 [max_time, batch_size, cell_state_size], 然後選擇outputs[-1], 這樣就得到了,最後時刻的output, cell_state_size 就是 hidden_size, 和GRU cell 裡面定義的是相同的,所以最後輸出 的形狀就是 [batch_size, cell_state_size]

outputs, last_states = tf.nn.dynamic_rnn( cell, inputs, dtype=tf.float64)outputs = tf.transpose(outputs, perm=[1, 0, 2])

  • 預測/ Prediction,最後再乘以weight加上bias, 就得到最後的結果了

weights = tf.Variable(tf.random_normal([hidden_size, num_classes], dtype = tf.float64))biases = tf.Variable(tf.random_normal([num_classes], dtype = tf.float64))pred = tf.matmul(outputs[-1], weights) + biases

  • Cost & Optimize ,cost 我們選擇cross entropy, 優化用AdamOptimizer, 為了方便評估模型,再加上一個accuracy (判斷正確的百分比)

# Define loss and optimizercost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=targets))# cost = tf.square(pred - targets)optimizer = tf.train.AdamOptimizer(learning_rate=0.01).minimize(cost)# Evaluate modelcorrect_pred = tf.equal(tf.argmax(pred,1), tf.argmax(targets,1))accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float64))

結果

Training iteration: 0 accuracy: 0.8Training iteration: 30 accuracy: 0.823529411765Training iteration: 60 accuracy: 0.858823529412Training iteration: 90 accuracy: 0.882352941176Training iteration: 120 accuracy: 0.941176470588Training iteration: 150 accuracy: 0.964705882353Training iteration: 180 accuracy: 0.976470588235Training iteration: 210 accuracy: 0.964705882353Training iteration: 240 accuracy: 0.976470588235Training iteration: 270 accuracy: 0.988235294118Testing accuracy: 0.833333333333

隨機選擇了12月的數據,作為測試數據, 最後得到測試數據accuracy 83%,訓練數據準確性幾乎到了100%。關鍵問題是數據太少,很容易overfit

觀察歷史數據發現有91個月,排期是前進的。91個月/121個月 = 75%,所以如果直接預測每個月都前進,結果準確性也能達到75%。 同樣的模型也適用於預測比特幣漲跌,股市漲跌,天氣陰晴等等。。。

更多內容關注專欄,Youtube

視頻?

www.youtube.com

Github

推薦閱讀:

這 8 份「Paper + Code」,你一定用得上 | PaperDaily #08
ENAS的原理和代碼解析
有趣的應用 | 使用RNN預測股票價格系列一
簡單的Char RNN生成文本
論文 | 深度學習實現目標跟蹤

TAG:TensorFlow | RNN | 美國綠卡 |