哈嘍,我是小白~
今兒和大家聊聊數(shù)據(jù)生成技術~
數(shù)據(jù)生成技術,能在數(shù)據(jù)稀缺的情況下提供足夠的訓練數(shù)據(jù),提升模型的泛化能力。通過模擬真實世界的復雜情況,數(shù)據(jù)生成技術幫助模型在多樣化場景下進行訓練和測試。它還能用于合成復雜或特定條件下的數(shù)據(jù),以應對偏差或過擬合等問題,提升模型的魯棒性。
今兒涉及到的十種數(shù)據(jù)生成技術有:
文末有總結性的干貨,大家記得領取~
一起來看下今天的內容!
1. 數(shù)據(jù)增強 (Data Augmentation)
數(shù)據(jù)增強主要在圖像、文本和語音等領域使用,通過對現(xiàn)有樣本進行各種變換,生成新的樣本。這些操作不會改變數(shù)據(jù)的標簽,但會改變數(shù)據(jù)的外觀、格式或結構。
原理
圖像數(shù)據(jù)增強包括旋轉、縮放、剪切、平移、翻轉等操作。數(shù)據(jù)增強的目標是通過小幅度變換數(shù)據(jù)來增加數(shù)據(jù)量,從而提高模型的泛化能力。
核心公式
數(shù)據(jù)增強的變換公式通常可以歸結為仿射變換:
其中 是二維的仿射變換矩陣, 是偏移向量。
具體的幾種操作:
旋轉:
這里 是旋轉角度。
縮放:
這里 和 分別是x軸和y軸的縮放系數(shù)。
剪切:
其中 和 是剪切系數(shù)。
推導
旋轉變換:
圖像的旋轉變換是仿射變換的一種形式,假設有一個點 ,經過角度 的旋轉后,得到新的點 :
縮放變換:
縮放即改變圖像的尺寸。通過將點 乘以縮放因子 和 :
剪切變換:
剪切操作會將圖像沿x軸或y軸進行傾斜:
這些幾何變換可以組合成更復雜的增強方式。
Python案例
此案例中,展示文本數(shù)據(jù)的增強,并進行不同的可視化分析。通過對文本的增廣操作,我們可以生成多個特征,例如:詞頻(Word Frequency)、詞嵌入(Word Embedding)等。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import LabelEncoder
from sklearn.manifold import TSNE
import random
# 設置隨機種子
np.random.seed(42)
random.seed(42)
# 虛擬文本數(shù)據(jù)集
texts = [
'I love data science and machine learning',
'Data analysis and visualization are key skills',
'Deep learning is a subset of machine learning',
'Data science involves statistics and programming',
'Machine learning models can be complex',
'Visualization helps to communicate data insights',
]
# 標簽:例如不同的文本類別(此處僅為展示效果)
labels = ['Tech', 'Tech', 'Tech', 'Tech', 'Tech', 'Tech']
# 數(shù)據(jù)增強:通過簡單的替換操作來模擬
def synonym_replacement(text):
synonyms = {
'love': 'like', 'data': 'information', 'science': 'knowledge', 'machine': 'AI',
'learning': 'training', 'analysis': 'analytics', 'visualization': 'plotting',
'statistics': 'math', 'programming': 'coding', 'complex': 'complicated'
}
words = text.split()
new_words = [synonyms.get(word, word) for word in words]
return ' '.join(new_words)
augmented_texts = [synonym_replacement(text) for text in texts]
# 詞頻統(tǒng)計和向量化:
vectorizer = CountVectorizer()
X_original = vectorizer.fit_transform(texts)
X_augmented = vectorizer.transform(augmented_texts) # 使用相同的詞匯表
# 將詞匯轉換為DataFrame以便可視化
word_freq_original = pd.DataFrame(X_original.toarray(), columns=vectorizer.get_feature_names_out())
word_freq_augmented = pd.DataFrame(X_augmented.toarray(), columns=vectorizer.get_feature_names_out())
# 數(shù)據(jù)增強前后詞頻對比可視化(柱狀圖)
def plot_word_frequencies():
word_sums_original = word_freq_original.sum(axis=0)
word_sums_augmented = word_freq_augmented.sum(axis=0)
plt.figure(figsize=(12, 6))
# 原始數(shù)據(jù)詞頻
plt.subplot(1, 2, 1)
word_sums_original.sort_values(ascending=False).plot(kind='bar', color='skyblue')
plt.title('Word Frequencies (Original)')
plt.xticks(rotation=45, ha='right')
# 增強后數(shù)據(jù)詞頻
plt.subplot(1, 2, 2)
word_sums_augmented.sort_values(ascending=False).plot(kind='bar', color='coral')
plt.title('Word Frequencies (Augmented)')
plt.xticks(rotation=45, ha='right')
# 生成文本嵌入(TF-IDF + PCA降維)
tfidf_vectorizer = TfidfVectorizer()
X_tfidf = tfidf_vectorizer.fit_transform(texts + augmented_texts)
# PCA降維
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_tfidf.toarray())
# 標簽編碼
label_encoder = LabelEncoder()
labels_encoded = label_encoder.fit_transform(labels * 2) # 兩倍,因為包含增強數(shù)據(jù)
# 數(shù)據(jù)增強后的PCA降維可視化
def plot_pca_embeddings():
plt.figure(figsize=(8, 6))
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k']
for i in np.unique(labels_encoded):
plt.scatter(X_pca[labels_encoded == i, 0], X_pca[labels_encoded == i, 1],
color=colors[i], label=label_encoder.inverse_transform([i])[0], alpha=0.7)
plt.title('PCA of Text Embeddings')
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.legend(loc='best')
# 組合繪圖函數(shù)
def combined_plot():
plt.figure(figsize=(16, 10))
# 詞頻柱狀圖
plt.subplot(2, 1, 1)
plot_word_frequencies()
# PCA降維可視化
plt.subplot(2, 1, 2)
plot_pca_embeddings()
plt.tight_layout()
plt.show()
# 運行生成圖形
combined_plot()
1. 數(shù)據(jù)增強:使用簡單的同義詞替換來模擬數(shù)據(jù)增強,這種方法雖然簡單,但可以展示增強后詞頻的變化。
2. 詞頻柱狀圖:左圖顯示原始數(shù)據(jù)的詞頻,右圖顯示增強數(shù)據(jù)的詞頻。通過比較兩個圖,可以觀察增強后哪些詞匯出現(xiàn)的頻率發(fā)生了變化。這有助于理解數(shù)據(jù)增強是否對文本結構產生了顯著影響。
3. PCA降維可視化:使用PCA(主成分分析)對文本的詞向量進行降維,展示文本在低維空間的分布。這有助于分析增強數(shù)據(jù)與原始數(shù)據(jù)在特征空間中的分布差異,是否有聚類、分離等現(xiàn)象。
2. SMOTE (Synthetic Minority Over-sampling Technique)
SMOTE 是一種處理不平衡數(shù)據(jù)集的過采樣方法。它通過對少數(shù)類樣本進行插值生成新的樣本,避免了簡單重復采樣帶來的過擬合風險。
原理
SMOTE 的核心思想是根據(jù)現(xiàn)有少數(shù)類樣本和它的鄰居進行線性插值生成新樣本。假設少數(shù)類樣本為 和它的最近鄰 ,則新生成的樣本為:
其中 是在 區(qū)間內的隨機數(shù)。
核心公式
生成新樣本公式:
其中:
推導
SMOTE 的推導相對簡單,基于線性插值。
1. 確定最近鄰樣本:
使用 KNN (K最近鄰) 找到少數(shù)類樣本 的最近鄰 。
2. 生成新樣本:
對于每個少數(shù)類樣本 ,找到其最近鄰樣本 。然后根據(jù)公式:
生成新的少數(shù)類樣本。這里的 是隨機生成的。
這種插值生成的新數(shù)據(jù)點位于少數(shù)類樣本及其鄰居之間的連線上,從而引入更多的多樣性。
Python案例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import plot_confusion_matrix
from sklearn.model_selection import train_test_split
from matplotlib.colors import ListedColormap
# 生成虛擬數(shù)據(jù)集
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0,
n_clusters_per_class=1, weights=[0.9, 0.1], flip_y=0, random_state=42)
# 可視化原始數(shù)據(jù)
def plot_data(X, y, title):
plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color='red', label='Class 0', alpha=0.7)
plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='blue', label='Class 1', alpha=0.7)
plt.title(title)
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
# 應用 SMOTE 技術
smote = SMOTE(sampling_strategy='auto', random_state=42)
X_res, y_res = smote.fit_resample(X, y)
# 決策邊界可視化
def plot_decision_boundary(X, y, model, title):
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.3, cmap=ListedColormap(('red', 'blue')))
plot_data(X, y, title)
# 訓練決策樹模型
clf_before = DecisionTreeClassifier(random_state=42)
clf_after = DecisionTreeClassifier(random_state=42)
# 劃分數(shù)據(jù)集并訓練
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
X_res_train, X_res_test, y_res_train, y_res_test = train_test_split(X_res, y_res, test_size=0.3, random_state=42)
clf_before.fit(X_train, y_train)
clf_after.fit(X_res_train, y_res_train)
# 繪制圖形
plt.figure(figsize=(15, 12))
# 原始數(shù)據(jù)
plt.subplot(2, 2, 1)
plot_data(X, y, 'Original Data (Imbalanced)')
# SMOTE 后的數(shù)據(jù)
plt.subplot(2, 2, 2)
plot_data(X_res, y_res, 'SMOTE Data (Balanced)')
# 原始數(shù)據(jù)的決策邊界
plt.subplot(2, 2, 3)
plot_decision_boundary(X_test, y_test, clf_before, 'Decision Boundary (Original Data)')
# SMOTE 后數(shù)據(jù)的決策邊界
plt.subplot(2, 2, 4)
plot_decision_boundary(X_res_test, y_res_test, clf_after, 'Decision Boundary (SMOTE Data)')
plt.tight_layout()
plt.show()
- 使用了
make_classification
生成一個不平衡的虛擬數(shù)據(jù)集,類別分布為90:10。 SMOTE
用于生成新的少數(shù)類樣本,以達到平衡數(shù)據(jù)的目的。
- 左上角是原始不平衡數(shù)據(jù)的散點圖,展示數(shù)據(jù)不平衡的情況。
- 右上角是應用SMOTE后的數(shù)據(jù)散點圖,展示了少數(shù)類樣本的增加。
- 左下和右下分別是原始數(shù)據(jù)與應用SMOTE后的數(shù)據(jù)的決策邊界可視化,可以看到SMOTE如何影響模型的學習。
3. 生成對抗網(wǎng)絡 (GANs)
GAN 是一種生成模型,通過對抗學習生成逼真的數(shù)據(jù)。它由兩個網(wǎng)絡組成:生成器 和判別器 。生成器嘗試生成逼真的數(shù)據(jù),判別器嘗試區(qū)分真實數(shù)據(jù)和生成的數(shù)據(jù)。
原理
GAN 通過對抗性訓練來學習數(shù)據(jù)的分布。生成器 接收隨機噪聲 作為輸入,輸出一個生成樣本 ,判別器 試圖判別該樣本是真實樣本還是生成的假樣本。通過這種博弈,生成器不斷改進,直到生成的數(shù)據(jù)足夠逼真。
核心公式
GAN 的目標是解決一個極大極小問題,其損失函數(shù)為:
其中:
- 是判別器對真實樣本 的輸出,表示該樣本為真實數(shù)據(jù)的概率
推導
1. 判別器的目標:
判別器 的目標是最大化對真實樣本的預測 ,同時最小化對生成樣本 的預測,即:
其中,第一項表示判別器希望對真實樣本的預測盡可能接近1,第二項表示對生成樣本的預測接近0。
2. 生成器的目標:
生成器 的目標是使生成的樣本 被判別器 誤認為是真實樣本,即最小化:
3. 對抗博弈:
判別器和生成器通過極大極小博弈進行優(yōu)化,生成器試圖最小化生成樣本被判別器識別為假樣本的概率,而判別器則試圖最大化對真實樣本和假樣本的正確區(qū)分。最終,GAN 的目標函數(shù)變?yōu)椋?/p>
最優(yōu)解
理論上,當判別器和生成器達到納什均衡時,生成器生成的樣本分布和真實數(shù)據(jù)的分布相同,此時 對于所有樣本 。
Python案例
生成對抗網(wǎng)絡(GAN, Generative Adversarial Network)是一種通過兩個神經網(wǎng)絡對抗訓練的技術,其中生成器(Generator)試圖生成逼真的數(shù)據(jù)樣本,而判別器(Discriminator)試圖區(qū)分生成數(shù)據(jù)和真實數(shù)據(jù)。我們可以用虛擬數(shù)據(jù)集(例如二維數(shù)據(jù)點)來展示GAN的訓練過程,并且使用數(shù)據(jù)分析圖來展示其效果。
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
# 生成真實數(shù)據(jù)的函數(shù),生成二維數(shù)據(jù)點
def real_data_distribution(num_samples):
return torch.randn(num_samples, 2) * 2 + torch.tensor([5, 5])
# 生成器類
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.Linear(2, 16),
nn.ReLU(),
nn.Linear(16, 2)
)
def forward(self, x):
return self.model(x)
# 判別器類
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Linear(2, 16),
nn.ReLU(),
nn.Linear(16, 1),
nn.Sigmoid()
)
def forward(self, x):
return self.model(x)
# 超參數(shù)
num_epochs = 5000
batch_size = 128
learning_rate = 0.001
# 初始化生成器和判別器
G = Generator()
D = Discriminator()
# 優(yōu)化器和損失函數(shù)
loss_fn = nn.BCELoss()
optimizer_G = optim.Adam(G.parameters(), lr=learning_rate)
optimizer_D = optim.Adam(D.parameters(), lr=learning_rate)
# 存儲損失值以繪制損失曲線
losses_G = []
losses_D = []
# 訓練GAN
for epoch in range(num_epochs):
# 訓練判別器
real_data = real_data_distribution(batch_size)
fake_data = G(torch.randn(batch_size, 2))
# 判別器對真實數(shù)據(jù)的預測
real_preds = D(real_data)
real_labels = torch.ones(batch_size, 1)
loss_real = loss_fn(real_preds, real_labels)
# 判別器對生成數(shù)據(jù)的預測
fake_preds = D(fake_data.detach()) # 生成數(shù)據(jù)梯度不回傳到生成器
fake_labels = torch.zeros(batch_size, 1)
loss_fake = loss_fn(fake_preds, fake_labels)
# 判別器總損失
loss_D = (loss_real + loss_fake) / 2
# 反向傳播更新判別器
optimizer_D.zero_grad()
loss_D.backward()
optimizer_D.step()
# 訓練生成器
fake_data = G(torch.randn(batch_size, 2))
preds = D(fake_data)
loss_G = loss_fn(preds, real_labels) # 生成器希望判別器認為其數(shù)據(jù)為真實
# 反向傳播更新生成器
optimizer_G.zero_grad()
loss_G.backward()
optimizer_G.step()
# 記錄損失
losses_G.append(loss_G.item())
losses_D.append(loss_D.item())
# 每1000次迭代打印一次損失
if epoch % 1000 == 0:
print(f'Epoch {epoch}: Generator Loss: {loss_G.item()}, Discriminator Loss: {loss_D.item()}')
# 繪制圖形
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
# 生成一些測試數(shù)據(jù)用于散點圖
real_data_test = real_data_distribution(500).detach().numpy()
fake_data_test = G(torch.randn(500, 2)).detach().numpy()
# 圖1:散點圖顯示真實數(shù)據(jù)和生成數(shù)據(jù)的分布
ax1.scatter(real_data_test[:, 0], real_data_test[:, 1], color='blue', label='Real Data', alpha=0.6)
ax1.scatter(fake_data_test[:, 0], fake_data_test[:, 1], color='red', label='Fake Data', alpha=0.6)
ax1.set_title('Real vs Generated Data')
ax1.legend()
ax1.grid(True)
# 圖2:生成器和判別器的損失曲線
ax2.plot(losses_G, label='Generator Loss', color='green')
ax2.plot(losses_D, label='Discriminator Loss', color='orange')
ax2.set_title('Generator and Discriminator Loss During Training')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Loss')
ax2.legend()
ax2.grid(True)
plt.tight_layout()
plt.show()
真實數(shù)據(jù)分布:我們使用 real_data_distribution
函數(shù)生成一個簡單的二維正態(tài)分布數(shù)據(jù)集,這樣可以直觀地在二維平面上展示數(shù)據(jù)點的分布。
生成器(Generator)和判別器(Discriminator):生成器試圖生成接近真實數(shù)據(jù)分布的二維點,判別器則嘗試區(qū)分生成的數(shù)據(jù)與真實數(shù)據(jù)。兩個模型的架構都使用簡單的多層感知機(MLP)網(wǎng)絡。
損失函數(shù)和優(yōu)化:使用二元交叉熵(BCELoss)作為生成器和判別器的損失函數(shù),并使用Adam優(yōu)化器進行梯度更新。
圖1 - 生成數(shù)據(jù)與真實數(shù)據(jù)的散點圖:這個圖能夠清晰地展示GAN生成的虛擬數(shù)據(jù)與真實數(shù)據(jù)的對比,幫助我們直觀地觀察生成器的效果。隨著訓練的進行,生成的數(shù)據(jù)點應該逐漸接近真實數(shù)據(jù)點的分布。
圖2 - 生成器和判別器的損失曲線:GAN的訓練過程常常不穩(wěn)定,監(jiān)控生成器和判別器的損失函數(shù)有助于理解訓練過程是否收斂,或者是否發(fā)生了模式崩潰(mode collapse)等問題。
4. 變分自編碼器 (VAE)
VAE 是一種生成模型,它通過編碼器將數(shù)據(jù)壓縮到一個潛在空間,再通過解碼器從潛在空間生成新的數(shù)據(jù)。
原理
VAE 假設數(shù)據(jù) 來自一個隱藏的潛在變量 ,目標是學習 的分布。VAE 使用變分推斷,通過最大化變分下界 (ELBO) 來逼近后驗分布。
核心公式
VAE 的目標是最大化對數(shù)似然 的變分下界:
其中:
推導
1. 邊緣似然:
數(shù)據(jù) 的邊緣似然可以通過積分潛在變量 得到:
但直接計算此積分非常困難。
2. 變分推斷:
為了避免直接計算,我們引入一個近似后驗分布 ,并將其分解為:
由于 KL 散度為正,因此可以得到變分下界 (ELBO):
3. 優(yōu)化目標:
VAE 的目標是最大化 ELBO。第一項是重構誤差,表示數(shù)據(jù) 和生成的樣本 之間的差異;第二項是 KL 散度,用于逼近 和先驗分布 的差異。
Python案例
我們使用虛擬數(shù)據(jù)集演示如何使用VAE生成數(shù)據(jù),并通過兩種不同的圖表(潛在空間的2D散點圖、重構后的數(shù)據(jù)對比圖)來進行分析。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import matplotlib.pyplot as plt
import numpy as np
# 設置隨機種子
torch.manual_seed(0)
np.random.seed(0)
# 生成虛擬數(shù)據(jù)集(例如,二維高斯分布)
data = np.random.randn(1000, 2)
dataset = TensorDataset(torch.tensor(data, dtype=torch.float32))
dataloader = DataLoader(dataset, batch_size=128, shuffle=True)
# 定義VAE的編碼器和解碼器結構
class VAE(nn.Module):
def __init__(self, input_dim=2, latent_dim=2):
super(VAE, self).__init__()
# 編碼器
self.encoder = nn.Sequential(
nn.Linear(input_dim, 16),
nn.ReLU(),
nn.Linear(16, latent_dim * 2) # 輸出均值和標準差
)
# 解碼器
self.decoder = nn.Sequential(
nn.Linear(latent_dim, 16),
nn.ReLU(),
nn.Linear(16, input_dim)
)
def reparameterize(self, mu, logvar):
std = torch.exp(0.5 * logvar)
eps = torch.randn_like(std)
return mu + eps * std
def forward(self, x):
# 編碼
x_encoded = self.encoder(x)
mu, logvar = torch.chunk(x_encoded, 2, dim=-1)
z = self.reparameterize(mu, logvar)
# 解碼
x_reconstructed = self.decoder(z)
return x_reconstructed, mu, logvar, z
# 定義損失函數(shù)(重構損失 + KL散度)
def loss_function(reconstructed_x, x, mu, logvar):
recon_loss = nn.functional.mse_loss(reconstructed_x, x, reduction='sum')
kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
return recon_loss + kl_loss
# 初始化模型、優(yōu)化器
vae = VAE(input_dim=2, latent_dim=2)
optimizer = optim.Adam(vae.parameters(), lr=1e-3)
# 訓練VAE
num_epochs = 100
vae.train()
for epoch in range(num_epochs):
total_loss = 0
for batch in dataloader:
x = batch[0]
optimizer.zero_grad()
reconstructed_x, mu, logvar, _ = vae(x)
loss = loss_function(reconstructed_x, x, mu, logvar)
loss.backward()
optimizer.step()
total_loss += loss.item()
if (epoch + 1) % 10 == 0:
print(f'Epoch {epoch+1}, Loss: {total_loss/len(dataset):.4f}')
# 獲取潛在空間中的數(shù)據(jù)分布
vae.eval()
with torch.no_grad():
all_z = []
all_data = []
all_reconstructed_data = []
for batch in dataloader:
x = batch[0]
reconstructed_x, _, _, z = vae(x)
all_z.append(z)
all_data.append(x)
all_reconstructed_data.append(reconstructed_x)
all_z = torch.cat(all_z, dim=0).numpy()
all_data = torch.cat(all_data, dim=0).numpy()
all_reconstructed_data = torch.cat(all_reconstructed_data, dim=0).numpy()
# 繪制圖形
plt.figure(figsize=(12, 6))
# 1. 潛在空間散點圖
plt.subplot(1, 2, 1)
plt.scatter(all_z[:, 0], all_z[:, 1], c='blue', label='Latent Space', alpha=0.6)
plt.title('Latent Space Distribution')
plt.xlabel('Latent Variable 1')
plt.ylabel('Latent Variable 2')
plt.legend()
# 2. 原始數(shù)據(jù)與重構數(shù)據(jù)對比
plt.subplot(1, 2, 2)
plt.scatter(all_data[:, 0], all_data[:, 1], c='green', label='Original Data', alpha=0.5)
plt.scatter(all_reconstructed_data[:, 0], all_reconstructed_data[:, 1], c='red', label='Reconstructed Data', alpha=0.5)
plt.title('Original vs Reconstructed Data')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
# 顯示圖像
plt.tight_layout()
plt.show()
- 潛在空間的2D散點圖:通過在潛在空間中繪制點,可以直觀了解VAE學習的潛在變量分布,查看是否有不同數(shù)據(jù)點的聚類或模式。
- 原始數(shù)據(jù)與重構數(shù)據(jù)的對比:這個圖展示了VAE在學習數(shù)據(jù)分布后的生成能力。通過比較原始數(shù)據(jù)與重構數(shù)據(jù),可以評估模型的性能。
5. 回歸模型的噪聲注入
在回歸任務中,通過在現(xiàn)有數(shù)據(jù)上添加隨機噪聲生成新樣本。這是一種簡單且有效的數(shù)據(jù)生成方法。
原理
我們通過將隨機噪聲注入到回歸模型的目標變量上,從而生成新的樣本。假設原始數(shù)據(jù)為 ,生成新數(shù)據(jù) 的方法是:
其中, 是服從高斯分布的噪聲項 。
核心公式
公式為:
其中 是原始數(shù)據(jù)的輸出, 是一個隨機噪聲,通常服從正態(tài)分布 。
推導
噪聲注入的推導非常簡單。假設我們有回歸模型 ,然后在輸出 上加入正態(tài)分布的噪聲 ,從而生成新的數(shù)據(jù)點。
這使得模型能夠在原始數(shù)據(jù)附近生成新的數(shù)據(jù)點,保持數(shù)據(jù)的多樣性,同時不改變數(shù)據(jù)的分布特性。
Python案例
使用“回歸模型的噪聲注入”來生成一個虛擬數(shù)據(jù)集,并分析其中的數(shù)據(jù)。噪聲注入的目的是為了增強模型的魯棒性,避免過擬合。在這個案例中,我們將使用線性回歸模型,并向目標變量添加高斯噪聲來生成虛擬數(shù)據(jù)。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
import seaborn as sns
# 設置隨機種子
np.random.seed(42)
# 生成虛擬數(shù)據(jù)集
n_samples = 100
X = 2 * np.random.rand(n_samples, 1)
true_slope = 3.5
true_intercept = 1.2
noise = np.random.randn(n_samples, 1) # 高斯噪聲
y_true = true_slope * X + true_intercept
y_noisy = y_true + noise # 加入噪聲
# 擬合線性回歸模型
lin_reg = LinearRegression()
lin_reg.fit(X, y_noisy)
y_pred = lin_reg.predict(X)
# 計算殘差
residuals = y_noisy - y_pred
# 繪圖
plt.figure(figsize=(16, 12))
# 1. 原始數(shù)據(jù)及擬合線
plt.subplot(2, 2, 1)
plt.scatter(X, y_noisy, color='blue', label='Noisy Data')
plt.plot(X, y_pred, color='red', label='Fitted Line', linewidth=2)
plt.title('Scatter Plot with Fitted Line', fontsize=14)
plt.xlabel('X', fontsize=12)
plt.ylabel('y', fontsize=12)
plt.legend()
# 2. 殘差圖
plt.subplot(2, 2, 2)
plt.scatter(X, residuals, color='green')
plt.axhline(y=0, color='red', linestyle='--')
plt.title('Residuals Plot', fontsize=14)
plt.xlabel('X', fontsize=12)
plt.ylabel('Residuals', fontsize=12)
# 3. 真實值 vs 預測值
plt.subplot(2, 2, 3)
plt.scatter(y_noisy, y_pred, color='purple')
plt.plot([min(y_noisy), max(y_noisy)], [min(y_noisy), max(y_noisy)], color='red', linestyle='--', linewidth=2)
plt.title('True vs Predicted Values', fontsize=14)
plt.xlabel('True Values', fontsize=12)
plt.ylabel('Predicted Values', fontsize=12)
# 4. 噪聲分布
plt.subplot(2, 2, 4)
sns.histplot(noise, kde=True, color='orange')
plt.title('Noise Distribution', fontsize=14)
plt.xlabel('Noise', fontsize=12)
plt.ylabel('Frequency', fontsize=12)
plt.tight_layout()
plt.show()
- 數(shù)據(jù)生成:使用線性模型 生成虛擬數(shù)據(jù),并注入高斯噪聲。
- 線性回歸模型:使用
sklearn
的LinearRegression
模型擬合數(shù)據(jù),并預測目標值。
- 散點圖展示了數(shù)據(jù)點及擬合的線性回歸模型。
- 殘差圖分析了預測值與實際值的偏差,檢查模型的擬合效果。
- 噪聲分布圖分析了噪聲的分布,確認噪聲是否符合正態(tài)分布。
6. 數(shù)據(jù)合成 (Synthetic Data Generation)
數(shù)據(jù)合成通過學習數(shù)據(jù)的分布,尤其適合生成無法直接獲取的敏感數(shù)據(jù)或具有隱私限制的數(shù)據(jù)。
原理
數(shù)據(jù)合成可以使用多種方法,例如高斯混合模型 (Gaussian Mixture Models, GMM) 或其他生成模型,從數(shù)據(jù)分布中進行采樣。
核心公式
假設數(shù)據(jù) 來自多個潛在的高斯分布,那么其概率密度為:
其中:
- 是第 個高斯分布的概率密度函數(shù),均值為 ,協(xié)方差矩陣為
推導
1. 高斯混合模型的參數(shù)估計:
使用 EM (期望最大化) 算法估計 GMM 模型的參數(shù):
2. 生成數(shù)據(jù):
通過 GMM 模型,從每個高斯分布中采樣生成新樣本。首先從混合權重 中選擇一個高斯分布,然后從該分布中生成新數(shù)據(jù)。
Python案例
生成一個模擬的信用卡交易數(shù)據(jù)集,包括交易金額、交易時間、卡號、商戶、交易成功與否等信息。使用多種可視化工具來進行數(shù)據(jù)分析,包括散點圖、直方圖和箱線圖,幫助我們理解數(shù)據(jù)的分布、變化及其關系。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 設置顏色風格
sns.set(style='whitegrid', palette='muted', color_codes=True)
# 生成虛擬數(shù)據(jù)集
np.random.seed(42)
n_samples = 1000
transaction_time = np.random.randint(0, 24, size=n_samples) # 交易時間:0-23小時
transaction_amount = np.random.exponential(scale=50, size=n_samples) # 交易金額:指數(shù)分布
merchant_id = np.random.choice(['Merchant_A', 'Merchant_B', 'Merchant_C', 'Merchant_D'], size=n_samples)
transaction_success = np.random.choice([0, 1], size=n_samples, p=[0.1, 0.9]) # 90% 交易成功
# 創(chuàng)建DataFrame
df = pd.DataFrame({
'Transaction Time': transaction_time,
'Transaction Amount': transaction_amount,
'Merchant': merchant_id,
'Success': transaction_success
})
# 創(chuàng)建圖像
fig, axes = plt.subplots(2, 2, figsize=(14, 10), constrained_layout=True)
# 圖1: 交易時間與交易金額的散點圖
sns.scatterplot(x='Transaction Time', y='Transaction Amount', hue='Success', data=df, ax=axes[0, 0], palette='bright')
axes[0, 0].set_title('Scatter Plot of Transaction Time vs Amount')
# 圖2: 交易金額的直方圖
sns.histplot(df['Transaction Amount'], bins=30, kde=True, color='orange', ax=axes[0, 1])
axes[0, 1].set_title('Histogram of Transaction Amount')
# 圖3: 每個商戶的交易金額箱線圖
sns.boxplot(x='Merchant', y='Transaction Amount', data=df, ax=axes[1, 0], palette='Set2')
axes[1, 0].set_title('Boxplot of Transaction Amount by Merchant')
# 圖4: 成功與失敗交易的金額分布
sns.violinplot(x='Success', y='Transaction Amount', data=df, ax=axes[1, 1], palette='muted')
axes[1, 1].set_title('Violin Plot of Transaction Amount by Success')
# 顯示圖像
plt.show()
散點圖(圖1):展示了交易金額和交易時間之間的關系,帶有不同的顏色區(qū)分交易是否成功。這樣可以幫助我們查看交易是否有時間相關性,以及失敗的交易是否集中在某些金額區(qū)間。
直方圖(圖2):用于查看交易金額的總體分布。通過直方圖,可以直觀地看出交易金額的集中程度以及是否有極端值。
箱線圖(圖3):展示了不同商戶的交易金額分布,包括中位數(shù)、四分位范圍以及可能的異常值。這有助于比較不同商戶之間的交易金額差異。
小提琴圖(圖4):結合了箱線圖和核密度估計,展示了成功和失敗交易的金額分布情況。這有助于深入了解交易金額的分布形態(tài),特別是成功和失敗交易之間的差異。
7. Bootstrap 重采樣
Bootstrap 是一種從原始數(shù)據(jù)集中通過有放回采樣生成新的數(shù)據(jù)集的方法,常用于估計模型的偏差和方差。
原理
從原始數(shù)據(jù)集中有放回采樣生成多個子數(shù)據(jù)集,每個子數(shù)據(jù)集的大小與原始數(shù)據(jù)集相同。通過這種方法生成的數(shù)據(jù)集可以用于模型訓練或評估。
核心公式
設數(shù)據(jù)集 ,從中有放回采樣 個子集 ,其中每個子集 包含 個樣本:
每次采樣時,數(shù)據(jù)集中的樣本可以被重復選擇。
推導
Bootstrap 的推導基于有放回采樣的思想。假設原始數(shù)據(jù)集中有 個樣本,通過有放回采樣生成新數(shù)據(jù)集,每次采樣從原始數(shù)據(jù)集中隨機選取一個樣本,可以重復選擇相同的樣本。
Python案例
假設我們有一組表示某商品銷量的虛擬數(shù)據(jù),我們希望通過 Bootstrap 重采樣來估計銷量的均值分布,并構建 95% 置信區(qū)間。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 設置隨機種子以保證可重復性
np.random.seed(42)
# 生成虛擬數(shù)據(jù)集,假設為商品銷量(正態(tài)分布,均值為50,標準差為10,樣本量為1000)
data = np.random.normal(loc=50, scale=10, size=1000)
# Bootstrap 重采樣的函數(shù)
def bootstrap(data, n_iterations=1000, sample_size=None):
if sample_size is None:
sample_size = len(data)
bootstrap_means = []
for _ in range(n_iterations):
sample = np.random.choice(data, size=sample_size, replace=True)
bootstrap_means.append(np.mean(sample))
return np.array(bootstrap_means)
# 執(zhí)行 Bootstrap 重采樣
n_iterations = 2000
bootstrap_means = bootstrap(data, n_iterations=n_iterations)
# 計算95%的置信區(qū)間
ci_lower = np.percentile(bootstrap_means, 2.5)
ci_upper = np.percentile(bootstrap_means, 97.5)
mean_estimate = np.mean(bootstrap_means)
# 設置圖形大小和樣式
plt.figure(figsize=(14, 10))
# 子圖 1: 原始數(shù)據(jù)的分布
plt.subplot(2, 2, 1)
sns.histplot(data, bins=30, kde=True, color='dodgerblue', edgecolor='black', alpha=0.7)
plt.title('Original Data Distribution (Sales)', fontsize=14, fontweight='bold')
plt.xlabel('Sales')
plt.ylabel('Frequency')
# 子圖 2: Bootstrap 重采樣均值的分布
plt.subplot(2, 2, 2)
sns.histplot(bootstrap_means, bins=30, kde=True, color='orange', edgecolor='black', alpha=0.7)
plt.axvline(mean_estimate, color='red', linestyle='--', linewidth=2, label=f'Mean: {mean_estimate:.2f}')
plt.axvline(ci_lower, color='green', linestyle='--', linewidth=2, label=f'95% CI Lower: {ci_lower:.2f}')
plt.axvline(ci_upper, color='green', linestyle='--', linewidth=2, label=f'95% CI Upper: {ci_upper:.2f}')
plt.title('Bootstrap Sample Mean Distribution', fontsize=14, fontweight='bold')
plt.xlabel('Mean Sales')
plt.ylabel('Frequency')
plt.legend()
# 子圖 3: Bootstrap 均值及其置信區(qū)間的折線圖
plt.subplot(2, 1, 2)
x_vals = np.arange(1, len(bootstrap_means) + 1)
plt.plot(x_vals, sorted(bootstrap_means), color='purple', label='Bootstrap Means')
plt.fill_between(x_vals, ci_lower, ci_upper, color='lightgreen', alpha=0.5, label=f'95% CI: [{ci_lower:.2f}, {ci_upper:.2f}]')
plt.axhline(mean_estimate, color='red', linestyle='--', label=f'Mean Estimate: {mean_estimate:.2f}')
plt.title('Bootstrap Means with Confidence Interval', fontsize=14, fontweight='bold')
plt.xlabel('Iteration')
plt.ylabel('Mean Sales')
plt.legend()
# 調整子圖布局
plt.tight_layout()
plt.show()
數(shù)據(jù)生成:np.random.normal()
:我們生成一個正態(tài)分布的數(shù)據(jù)集,表示商品的銷量,均值為50,標準差為10,樣本量為1000。
Bootstrap 重采樣:bootstrap()
:通過隨機重采樣多次計算數(shù)據(jù)集的均值。通過 np.random.choice()
函數(shù),每次有放回地抽取樣本進行重采樣。ci_lower
和 ci_upper
:通過 np.percentile()
計算95%置信區(qū)間的上下界。
- 子圖1:繪制原始數(shù)據(jù)的直方圖,展示銷量分布。
- 子圖2:繪制 Bootstrap 重采樣后的均值分布。通過直方圖和核密度估計(KDE)展示重采樣均值的分布,并標記置信區(qū)間和均值。
- 子圖3:繪制 Bootstrap 均值隨迭代次數(shù)的變化,并通過陰影區(qū)域展示95%置信區(qū)間。
8. 時間序列生成技術
對于時間序列數(shù)據(jù),常使用AR(自回歸)、MA(移動平均)、ARIMA(自回歸積分移動平均)、LSTM等模型生成新的時間序列數(shù)據(jù)。
原理
時間序列生成的核心是利用歷史數(shù)據(jù)預測未來數(shù)據(jù)。經典方法包括自回歸模型 (AR) 和移動平均模型 (MA),而 LSTM 等深度學習方法也被廣泛應用于復雜時間序列生成。
核心公式
自回歸模型 (AR):
其中 是當前時間點的值, 是模型參數(shù), 是誤差項。
移動平均模型 (MA):
其中 是誤差項, 是模型參數(shù)。
推導
1. 自回歸模型:
AR 模型假設當前時間點的值 是過去 個時間點的線性組合加上誤差項。通過最小化誤差的平方和,可以使用普通最小二乘法估計參數(shù) 。
2. 移動平均模型:
MA 模型假設當前值是過去誤差的線性組合。通過估計歷史誤差項,可以構建出未來的預測值。
Python案例
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.graphics.tsaplots import plot_acf
# 設置隨機種子,便于復現(xiàn)
np.random.seed(42)
# 生成虛擬時間序列數(shù)據(jù)(模擬ARIMA模型生成的時間序列)
n = 500
time = np.arange(n)
# 設置初始值和一些噪音
initial_value = 50
noise = np.random.normal(0, 1, n)
# 模擬一個簡單的隨機游走過程
data = np.cumsum(noise) + initial_value
# 創(chuàng)建一個DataFrame來存儲時間和生成的數(shù)據(jù)
df = pd.DataFrame({'Time': time, 'Value': data})
# 開始繪制圖形
plt.figure(figsize=(12, 10))
# 子圖1:時間序列折線圖
plt.subplot(3, 1, 1)
plt.plot(df['Time'], df['Value'], color='blue', label='Time Series', linewidth=2)
plt.title('Generated Time Series')
plt.xlabel('Time')
plt.ylabel('Value')
plt.grid(True)
plt.legend()
# 子圖2:時間序列的自相關圖
plt.subplot(3, 1, 2)
plot_acf(df['Value'], lags=40, ax=plt.gca())
plt.title('Autocorrelation Function (ACF)')
plt.grid(True)
# 子圖3:時間序列的直方圖
plt.subplot(3, 1, 3)
sns.histplot(df['Value'], bins=30, kde=True, color='orange')
plt.title('Histogram of Time Series Values')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.grid(True)
# 調整子圖布局
plt.tight_layout()
# 顯示圖像
plt.show()
- 時間序列折線圖:展示了生成的時間序列數(shù)據(jù)的趨勢,可以明顯看到隨著時間推移的波動情況。
- 自相關圖:通過觀察滯后值的相關性,判斷時間序列是否平穩(wěn),滯后效應可以幫助構建更復雜的預測模型。
- 直方圖:幫助分析生成數(shù)據(jù)的分布是否呈現(xiàn)出正態(tài)分布,或有偏斜等特征,有助于更深入理解數(shù)據(jù)的統(tǒng)計特性。
9. 回歸樹模擬 (Regression Tree Simulation)
回歸樹模擬是一種基于決策樹的生成技術,通常用于回歸任務中的數(shù)據(jù)生成。它通過決策樹模型學習數(shù)據(jù)的分段關系,并利用這些關系生成新的數(shù)據(jù)點。
原理
回歸樹模擬通過遞歸地劃分特征空間,構建一個樹形結構,每個葉節(jié)點對應于特定的預測值?;貧w樹的目標是通過最小化誤差來找到最佳的分裂點和分裂方式。
在訓練完成后,回歸樹可以通過在各個分支中生成新的樣本來模擬數(shù)據(jù)分布。新數(shù)據(jù)點可以根據(jù)訓練樹的分裂規(guī)則進行采樣,以模擬原始數(shù)據(jù)的分布。
核心公式
回歸樹的目標是最小化節(jié)點中的均方誤差 (MSE),定義為:
其中:
- 表示節(jié)點 中的數(shù)據(jù)點數(shù)量
- 表示節(jié)點 中所有數(shù)據(jù)點的均值
推導
1. 分裂準則:
在每個節(jié)點,回歸樹通過尋找最佳分裂點來最小化誤差。分裂準則可以是均方誤差 (MSE),即選擇能夠使 MSE 最小的特征和分裂點:
其中 和 分別是左右分支的樣本數(shù), 和 分別是左右子節(jié)點的均方誤差。
2. 生成新數(shù)據(jù):
訓練好的回歸樹可以用于生成新數(shù)據(jù)。通過隨機選擇特征值并根據(jù)決策樹的分支規(guī)則進行采樣,新的樣本將遵循與原始數(shù)據(jù)相似的分布。
3. 遞歸生成:
樹的葉節(jié)點對應于局部數(shù)據(jù)的平均值或預測值,因此新的樣本可以在葉節(jié)點生成。根據(jù)節(jié)點的結構,每個新樣本的特征值會依賴于其通過的樹路徑。
Python案例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import seaborn as sns
# 生成虛擬數(shù)據(jù)集
np.random.seed(42)
X, y = make_regression(n_samples=1000, n_features=4, noise=0.1, random_state=42)
# 分割數(shù)據(jù)集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 創(chuàng)建并訓練回歸樹模型
tree_model = DecisionTreeRegressor(max_depth=4, random_state=42)
tree_model.fit(X_train, y_train)
# 預測
y_pred = tree_model.predict(X_test)
# 計算均方誤差
mse = mean_squared_error(y_test, y_pred)
print(f'Mean Squared Error: {mse:.2f}')
# 創(chuàng)建繪圖
fig, ax = plt.subplots(2, 2, figsize=(16, 12), constrained_layout=True)
# 1. 可視化回歸樹結構
ax[0, 0].set_title('Regression Tree Structure', fontsize=14, color='darkblue')
plot_tree(tree_model, filled=True, feature_names=[f'Feature {i}' for i in range(1, 5)], ax=ax[0, 0], impurity=False)
# 2. 特征重要性可視化
feature_importances = tree_model.feature_importances_
ax[0, 1].set_title('Feature Importance', fontsize=14, color='darkgreen')
sns.barplot(x=[f'Feature {i}' for i in range(1, 5)], y=feature_importances, palette='bright', ax=ax[0, 1])
ax[0, 1].set_ylabel('Importance')
# 3. 真實值與預測值對比散點圖
ax[1, 0].set_title('True vs Predicted Values', fontsize=14, color='darkred')
sns.scatterplot(x=y_test, y=y_pred, ax=ax[1, 0], color='orange', s=60)
ax[1, 0].set_xlabel('True Values')
ax[1, 0].set_ylabel('Predicted Values')
ax[1, 0].plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='red', lw=2) # 參考線
# 4. 殘差分析
residuals = y_test - y_pred
ax[1, 1].set_title('Residuals Plot', fontsize=14, color='purple')
sns.histplot(residuals, bins=20, kde=True, color='purple', ax=ax[1, 1])
ax[1, 1].set_xlabel('Residuals')
ax[1, 1].set_ylabel('Frequency')
# 展示圖像
plt.suptitle('Regression Tree Analysis with Multiple Visualizations', fontsize=16, color='black')
plt.show()
- 數(shù)據(jù)生成與分割:我們使用
make_regression
函數(shù)生成了一個虛擬的回歸數(shù)據(jù)集,包含200個樣本和4個特征。我們將數(shù)據(jù)集分為訓練集和測試集。 - 回歸樹模型訓練:我們使用
DecisionTreeRegressor
進行回歸建模,并設置max_depth=4
限制樹的深度,避免過擬合。
- 回歸樹結構圖:使用
plot_tree
展示回歸樹的結構,直觀了解如何通過決策過程對數(shù)據(jù)進行分割。 - 特征重要性圖:通過
feature_importances_
屬性提取特征的重要性,并使用seaborn.barplot
繪制條形圖。 - 真實值與預測值對比圖:使用
seaborn.scatterplot
繪制散點圖,顯示模型的擬合效果,并添加參考線。 - 殘差分析:通過
seaborn.histplot
繪制殘差分布圖,并使用KDE平滑顯示殘差分布的形態(tài),評估模型是否存在系統(tǒng)性偏差。
10. 蒙特卡洛采樣 (Monte Carlo Sampling)
蒙特卡洛采樣是一種基于隨機化的數(shù)值方法,廣泛應用于數(shù)值積分、優(yōu)化和生成數(shù)據(jù)等任務。通過對隨機變量進行大量采樣來估計目標分布,可以生成符合目標分布的新數(shù)據(jù)。
原理
蒙特卡洛方法的核心思想是通過對復雜分布的大量隨機采樣來逼近其期望值。假設目標分布 難以直接從解析表達式中獲取,則可以通過隨機生成樣本來估計該分布。
蒙特卡洛采樣可以用于從各種復雜的分布中生成數(shù)據(jù),例如高維空間中的隨機變量。在機器學習中,常用于從模型的預測分布中生成數(shù)據(jù),或者用來估計期望和方差等統(tǒng)計量。
核心公式
蒙特卡洛估計的公式為:
其中:
推導
1. 隨機采樣:
蒙特卡洛方法通過從分布 中采樣得到 ,并利用這些樣本來近似計算期望值。若直接從目標分布 采樣較難,可以使用重要性采樣等變種方法來進行采樣。
2. 重要性采樣:
當無法直接從目標分布 采樣時,可以從一個易于采樣的分布 中采樣,并通過加權修正采樣值:
其中, 是重要性權重,用于修正從 中采樣的偏差。
3. 生成數(shù)據(jù):
蒙特卡洛采樣廣泛應用于數(shù)據(jù)生成任務。通過從模型的預測分布中大量采樣,可以生成符合模型假設的新數(shù)據(jù)。具體應用中,蒙特卡洛方法常用于模擬復雜系統(tǒng)(如物理模擬、金融模型等),并通過采樣的方式生成大量數(shù)據(jù)來分析系統(tǒng)的行為。
4. 方差收斂:
蒙特卡洛方法的估計誤差隨采樣次數(shù) 增加而減少,誤差的期望為 ,即通過增加采樣數(shù)量可以有效降低估計方差。
Python案例
假設有一個金融模型,涉及兩個隨機變量:資產收益率和波動率。我們使用蒙特卡洛采樣生成資產收益率和波動率的虛擬數(shù)據(jù),并分析其分布特性和相互關系。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 設置隨機種子
np.random.seed(42)
# 蒙特卡洛采樣 - 假設收益率服從正態(tài)分布,波動率服從對數(shù)正態(tài)分布
n_samples = 10000
mean_return = 0.05
std_return = 0.1
mean_volatility = 0.2
std_volatility = 0.05
# 生成資產收益率(正態(tài)分布)和波動率(對數(shù)正態(tài)分布)的虛擬數(shù)據(jù)
returns = np.random.normal(loc=mean_return, scale=std_return, size=n_samples)
volatility = np.random.lognormal(mean=np.log(mean_volatility), sigma=std_volatility, size=n_samples)
# 創(chuàng)建圖形
plt.figure(figsize=(12, 8))
# 1. 資產收益率的直方圖
plt.subplot(2, 2, 1)
sns.histplot(returns, bins=50, color='blue', kde=True, alpha=0.7)
plt.title('Asset Returns Distribution')
plt.xlabel('Returns')
plt.ylabel('Frequency')
# 2. 波動率的直方圖
plt.subplot(2, 2, 2)
sns.histplot(volatility, bins=50, color='green', kde=True, alpha=0.7)
plt.title('Volatility Distribution')
plt.xlabel('Volatility')
plt.ylabel('Frequency')
# 3. 收益率與波動率的散點圖
plt.subplot(2, 2, 3)
plt.scatter(returns, volatility, color='red', alpha=0.3)
plt.title('Scatter Plot: Returns vs Volatility')
plt.xlabel('Returns')
plt.ylabel('Volatility')
# 4. 收益率與波動率的聯(lián)合密度圖
plt.subplot(2, 2, 4)
sns.kdeplot(x=returns, y=volatility, cmap='magma', fill=True, thresh=0.05)
plt.title('Joint Density Plot: Returns vs Volatility')
plt.xlabel('Returns')
plt.ylabel('Volatility')
# 調整布局,避免重疊
plt.tight_layout()
plt.show()
- 資產收益率的直方圖:藍色的直方圖展示了資產收益率的頻率分布,結合核密度估計線可以看到其為正態(tài)分布的形狀。
- 波動率的直方圖:綠色的直方圖展示了波動率的分布,它符合對數(shù)正態(tài)分布,且右側尾部稍長。
- 收益率與波動率的散點圖:紅色的散點圖展示了兩者的相互關系,可以觀察到收益率與波動率之間是否有相關性(比如,波動率高時收益率較低)。
- 收益率與波動率的聯(lián)合密度圖:通過密度估計圖展示了收益率和波動率的聯(lián)合分布情況,顏色深淺反映了樣本的密度。