# 7 循環神經網路
可用於解決資料之間具有序列依賴關係的問題。</br>
例如:自然語言處理、語音處理、音樂生成、蛋白質序列分析、影片理解與分析、股票預測...
## 7.1 序列問題和模型
資料之間具有序列關係的預測問題,就是根據當前時刻之前的所有序列資料,對當前時刻的目標值進行預測。
例如:</br>
根據一支股票的所有歷史資料預測當前時刻股票的價格。$x_t$ 表示時刻 $t$ 的資料特徵,$y_t$ 表示希望預測的 $t$ 時刻的目標值。和任何監督是學習一樣,序列資料的預測就是要學習一個映射或函數 $f:(x_1, x_2, \cdot\cdot\cdot, x_t) \rightarrow y_t$,即根據 $t$ 時刻之前的所有時刻的資料特徵 $(x_1, x_2, \cdot\cdot\cdot, x_t)$ 去預測 $t$ 時刻的目標值 $y_t$。</br>
若 $x_t$ 和 $y_t$ 是同一類型的資料,如 $x_t$ 表示 $t$ 時刻的股票價格,$y_t$ 表示 $t$ 時刻預測的目標價格,即 $t+1$ 時刻的股票價格 $y_t = x_{t+1}$ ,那麼這樣的序列資料預測問題稱為 自回歸 問題。
### 7.1.1 股票價格問預測問題
用 pandas 套件讀取 CVS 格式檔案 sp500.cvs 中的股市資料
```python=
import pandas as pd
data = pd.read_csv('sp500.csv')
data.head()
```
### 7.1.2 機率序列模型和語言模型
#### 1. 機率序列模型
序列資料的預測問題,有時並不需要直接對序列資料及目標值的函數關係建模,而是根據序列資料來預測目標值的設定值機率。$y_t$ ~ $p(y_t|x_1, \cdot\cdot\cdot, x_t)$
#### 2. 語言模型
對敘述(句子)建模,以確定一個句子出現的機率。假設一個句子由詞 $(w_1, w_2, \cdot\cdot\cdot, w_n)$ 組成,句子的機率可用 $P(w_1, w_2, \cdot\cdot\cdot, w_n)$ 表示。
\begin{equation}
P(w_1, w_2, \cdot\cdot\cdot, w_n) = P(w_1) * P(w_2|w_1) * P(w_3|w_1, w_2) * \cdot\cdot\cdot * P(w_n|w_1, w_2, \cdot\cdot\cdot, w_2)
\end{equation}
### 7.1.3 自回歸模型
對當前時刻預測的目標就是下一時刻資料的自回歸問題所建立的預測模型稱為自回歸模型 (Auto Regressive Model ,AR模型)。</br>
如果真實資料 $x_t$ 只依賴之前長度為 $\tau$ 的資料 $(x_{t-\tau}, \cdot\cdot\cdot, x_{t-1})$ ,則稱這種序列資料滿足馬可夫性質,這樣的自回歸模型稱為馬可夫模型。</br>
最簡單的自回歸模型,假設 $x_{t-\tau}, \cdot\cdot\cdot, x_{t-1}$ 和 $x_t$ 之間滿足線性關係
\begin{equation}
x_t = a_0 + a_1x_{t-1} + \cdot\cdot\cdot + a_{\tau}x_{t-\tau} + \epsilon
\end{equation}
### 7.1.4 生成自回歸資料
```python=
import numpy as np
import matplotlib.pyplot as plt
def gen_seq_data_from_function(f, ts):
return f(ts)
T = 5000
x = gen_seq_data_from_function(lambda ts:np.sin(ts*0.1) + np.cos(ts*0.2), np.arange(0, T))
plt.plot(x[:500])
plt.show()
```

從一些初始資料生成沒有週期性的序列資料:
1. 選擇合適的係數 $(a_0, a_1, \cdot\cdot\cdot, a_{\tau})$
2. 生成最初的 $\tau$ 個隨機資料
3. 多次使用最簡單的自回歸模型公式,生成下一個資料
研究表明:只有在係數組成的方程式 $x^{\tau} - a_0x^{\tau - 1} - a_1x^{\tau - 2} - \cdot\cdot\cdot - a_{\tau}$ 的根的絕對值不超過1時,自回歸模型才是穩定的;不然生成資料是不穩定的。
```python=
import numpy as np
import matplotlib.pyplot as plt
# init_coefficients() 用於生成穩定的自回歸模型的係數
def init_coefficients(n):
while True:
a = np.random.random(n) - 0.5
coefficients = np.append(1, -a)
if np.max(np.abs(np.roots(coefficients))) < 1:
return a
def generate_data(n, data_n, noise_value = 1, k = 3):
a = init_coefficients(n + 1)
x = np.zeros(data_n + n * (k + 1))
x_noise = np.zeros(data_n + n * (k + 1))
x_noise[:n] = np.random.randn(n)
n_all = data_n + n * k
for i in range(n_all):
x[n + i] = np.dot(x_noise[i:n + i][::-1], a[1:]) + a[0]
x_noise[n + i] = x[n + i] + noise_value * np.random.randn()
x_noise = x_noise[k*n:]
x = x[k*n:]
return x_noise, x
x,_ = generate_data(5, 100)
plt.plot(x[:80])
plt.show()
```

### 7.1.5 時間窗方法
在一對一神經網路中,每個樣本的長度必須相同,即每個樣本的特徵數目必須相同。用於處理序列資料就是從序列資料中截取長度相同的子序列作為一個整體,組成一個樣本資料的特徵。對一個序列資料 $x^{(i)}$,如果總是用 $x^{(i)}$ 之前的 $T$ 個(包含 $x^{(i)}$ ) 序列元素 $(x^{(i - T + 1)}, \cdot\cdot\cdot, x^{(i - 1)}, x^{(i)})$ 作為一個樣本的資料特徵去預測 $y^{(i)}$ ,就在一定程度考慮了不同 $x^{(i)}$ 之間的序列相關性。
### 7.1.6 時間窗取樣
```python=
import numpy as np
import matplotlib.pyplot as plt
def gen_seq_data_from_function(f, ts):
return f(ts)
def gen_data_set(x, T, percentage = 0.9):
L = T + 1
data_set = []
for i in range(len(x) - (T + 1)):
data_set.append(x[i:i + T + 1])
data_set = np.array(data_set)
row = round(percentage * data_set.shape[0])
train = data_set[:int(row), :]
np.random.shuffle(train)
x_train = train[:, :-1]
y_train = train[:, -1]
x_test = data_set[int(row):, :-1]
y_test = data_set[int(row):, -1]
return [x_train, y_train, x_test, y_test]
x = gen_seq_data_from_function(lambda ts:np.sin(ts*0.1) + np.cos(ts*0.2), np.arange(0, 5000))
x_train, y_train, x_test, y_test = gen_data_set(x, 50)
y_train = y_train.reshape(-1, 1)
print(x_train.shape, y_train.shape)
```
### 7.1.7 時間窗方法的建模和訓練!










問題:
* 自回歸模型的應用?
* 時間窗方法在處理序列資料時的作用是什麼?