精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

深度學(xué)習(xí)實戰(zhàn):手把手教你構(gòu)建多任務(wù)、多標簽?zāi)P?/h1>

人工智能 機器學(xué)習(xí)
多任務(wù)多標簽?zāi)P褪乾F(xiàn)代機器學(xué)習(xí)中的基礎(chǔ)架構(gòu),這個任務(wù)在概念上很簡單 -訓(xùn)練一個模型同時預(yù)測多個任務(wù)的多個輸出。

多任務(wù)多標簽?zāi)P褪乾F(xiàn)代機器學(xué)習(xí)中的基礎(chǔ)架構(gòu),這個任務(wù)在概念上很簡單 -訓(xùn)練一個模型同時預(yù)測多個任務(wù)的多個輸出。

在本文中,我們將基于流行的 MovieLens 數(shù)據(jù)集,使用稀疏特征來創(chuàng)建一個多任務(wù)多標簽?zāi)P?并逐步介紹整個過程。所以本文將涵蓋數(shù)據(jù)準備、模型構(gòu)建、訓(xùn)練循環(huán)、模型診斷,最后使用 Ray Serve 部署模型的全部流程。

1.設(shè)置環(huán)境

在深入代碼之前,請確保安裝了必要的庫(以下不是詳盡列表):

pip install pandas scikit-learn torch ray[serve] matplotlib requests tensorboard

我們在這里使用的數(shù)據(jù)集足夠小,所以可以使用 CPU 進行訓(xùn)練。

2.準備數(shù)據(jù)集

我們將從創(chuàng)建用于處理 MovieLens 數(shù)據(jù)集的下載、預(yù)處理的類開始,然后將數(shù)據(jù)分割為訓(xùn)練集和測試集。

MovieLens數(shù)據(jù)集包含有關(guān)用戶、電影及其評分的信息,我們將用它來預(yù)測評分(回歸任務(wù))和用戶是否喜歡這部電影(二元分類任務(wù))。

import os  
 import pandas as pd  
 from sklearn.model_selection import train_test_split  
 from sklearn.preprocessing import LabelEncoder  
 import torch  
 from torch.utils.data import Dataset, DataLoader  
 import zipfile  
 import io  
 import requests  
   
 class MovieLensDataset(Dataset):  
   
     def __init__(self, dataset_version="small", data_dir="data"):  
         print("Initializing MovieLensDataset...")  
         if not os.path.exists(data_dir):  
             os.makedirs(data_dir)  
           
         if dataset_version == "small":  
             url = "https://files.grouplens.org/datasets/movielens/ml-latest-small.zip"  
             local_zip_path = os.path.join(data_dir, "ml-latest-small.zip")  
             file_path = 'ml-latest-small/ratings.csv'  
             parquet_path = os.path.join(data_dir, "ml-latest-small.parquet")  
         elif dataset_version == "full":  
             url = "https://files.grouplens.org/datasets/movielens/ml-latest.zip"  
             local_zip_path = os.path.join(data_dir, "ml-latest.zip")  
             file_path = 'ml-latest/ratings.csv'  
             parquet_path = os.path.join(data_dir, "ml-latest.parquet")  
         else:  
             raise ValueError("Invalid dataset_version. Choose 'small' or 'full'.")  
           
         if os.path.exists(parquet_path):  
             print(f"Loading dataset from {parquet_path}...")  
             movielens = pd.read_parquet(parquet_path)  
         else:  
             if not os.path.exists(local_zip_path):  
                 print(f"Downloading {dataset_version} dataset from {url}...")  
                 response = requests.get(url)  
                 with open(local_zip_path, "wb") as f:  
                     f.write(response.content)  
               
             with zipfile.ZipFile(local_zip_path, "r") as z:  
                 with z.open(file_path) as f:  
                     movielens = pd.read_csv(f, usecols=['userId', 'movieId', 'rating'], low_memory=True)  
             movielens.to_parquet(parquet_path, index=False)  
         movielens['liked'] = (movielens['rating'] >= 4).astype(int)  
         self.user_encoder = LabelEncoder()  
         self.movie_encoder = LabelEncoder()  
         movielens['user'] = self.user_encoder.fit_transform(movielens['userId'])  
         movielens['movie'] = self.movie_encoder.fit_transform(movielens['movieId'])  
         self.train_df, self.test_df = train_test_split(movielens, test_size=0.2, random_state=42)  
       
     def get_data(self, split="train"):  
         if split == "train":  
             data = self.train_df  
         elif split == "test":  
             data = self.test_df  
         else:  
             raise ValueError("Invalid split. Choose 'train' or 'test'.")  
           
         dense_features = torch.tensor(data[['user', 'movie']].values, dtype=torch.long)  
         labels = torch.tensor(data[['rating', 'liked']].values, dtype=torch.float32)  
           
         return dense_features, labels  
       
     def get_encoders(self):  
         return self.user_encoder, self.movie_encoder

定義了 MovieLensDataset,就可以將訓(xùn)練集和評估集加載到內(nèi)存中

# Example usage with a single dataset object  
 print("Creating MovieLens dataset...")  
 # Feel free to use dataset_version="full" if you are using  
 # a GPU  
 dataset = MovieLensDataset(dataset_version="small")  
   
 print("Getting training data...")  
 train_dense_features, train_labels = dataset.get_data(split="train")  
 print("Getting testing data...")  
 test_dense_features, test_labels = dataset.get_data(split="test")  
 # Create DataLoader for training and testing  
 train_loader = DataLoader(torch.utils.data.TensorDataset(train_dense_features, train_labels), batch_size=64, shuffle=True)  
 test_loader = DataLoader(torch.utils.data.TensorDataset(test_dense_features, test_labels), batch_size=64, shuffle=False)  
 print("Accessing encoders...")  
 user_encoder, movie_encoder = dataset.get_encoders()  
 print("Setup complete.")

3.定義多任務(wù)多標簽?zāi)P?/h4>

我們將定義一個基本的 PyTorch 模型,處理兩個任務(wù):預(yù)測評分(回歸)和用戶是否喜歡這部電影(二元分類)。

模型使用稀疏嵌入來表示用戶和電影,并有共享層,這些共享層會輸入到兩個單獨的輸出層。

通過在任務(wù)之間共享一些層,并為每個特定任務(wù)的輸出設(shè)置單獨的層,該模型利用了共享表示,同時仍然針對每個任務(wù)定制其預(yù)測。

from torch import nn  
   
 class MultiTaskMovieLensModel(nn.Module):  
     def __init__(self, n_users, n_movies, embedding_size, hidden_size):  
         super(MultiTaskMovieLensModel, self).__init__()  
         self.user_embedding = nn.Embedding(n_users, embedding_size)  
         self.movie_embedding = nn.Embedding(n_movies, embedding_size)  
         self.shared_layer = nn.Linear(embedding_size * 2, hidden_size)  
         self.shared_activation = nn.ReLU()  
         self.task1_fc = nn.Linear(hidden_size, 1)  
         self.task2_fc = nn.Linear(hidden_size, 1)  
         self.task2_activation = nn.Sigmoid()  
   
     def forward(self, x):  
         user = x[:, 0]  
         movie = x[:, 1]  
         user_embed = self.user_embedding(user)  
         movie_embed = self.movie_embedding(movie)  
         combined = torch.cat((user_embed, movie_embed), dim=1)  
         shared_out = self.shared_activation(self.shared_layer(combined))  
         rating_out = self.task1_fc(shared_out)  
         liked_out = self.task2_fc(shared_out)  
         liked_out = self.task2_activation(liked_out)  
         return rating_out, liked_out

輸入 (x):

  • 輸入 x 預(yù)期是一個 2D 張量,其中每行包含一個用戶 ID 和一個電影 ID。

用戶和電影嵌入:

  • user = x[:, 0]: 從第一列提取用戶 ID。
  • movie = x[:, 1]: 從第二列提取電影 ID。
  • user_embed 和 movie_embed 是對應(yīng)這些 ID 的嵌入。

連接:

  • combined = torch.cat((user_embed, movie_embed), dim=1): 沿特征維度連接用戶和電影嵌入。

共享層:

  • shared_out = self.shared_activation(self.shared_layer(combined)): 將組合的嵌入通過共享的全連接層和激活函數(shù)。

任務(wù)特定輸出:

  • rating_out = self.task1_fc(shared_out): 從第一個任務(wù)特定層輸出預(yù)測評分。
  • liked_out = self.task2_fc(shared_out): 輸出用戶是否喜歡電影的原始分數(shù)。
  • liked_out = self.task2_activation(liked_out): 原始分數(shù)通過 sigmoid 函數(shù)轉(zhuǎn)換為概率。

返回 :

模型返回兩個輸出:

  • rating_out:預(yù)測的評分(回歸輸出)。
  • liked_out: 用戶喜歡電影的概率(分類輸出)。

4.訓(xùn)練循環(huán)

首先,用一些任意選擇的超參數(shù)(嵌入維度和隱藏層中的神經(jīng)元數(shù)量)實例化我們的模型。對于回歸任務(wù)將使用均方誤差損失,對于分類任務(wù),將使用二元交叉熵。

我們可以通過它們的初始值來歸一化兩個損失,以確保它們都大致處于相似的尺度(這里也可以使用不確定性加權(quán)來歸一化損失)

然后將使用數(shù)據(jù)加載器訓(xùn)練模型,并跟蹤兩個任務(wù)的損失。損失將被繪制成圖表,以可視化模型在評估集上隨時間的學(xué)習(xí)和泛化情況。

import torch.optim as optim  
 import matplotlib.pyplot as plt  
   
 # Check if GPU is available  
 device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  
 print(f"Using device: {device}")  
 embedding_size = 16  
 hidden_size = 32  
 n_users = len(dataset.get_encoders()[0].classes_)  
 n_movies = len(dataset.get_encoders()[1].classes_)  
 model = MultiTaskMovieLensModel(n_users, n_movies, embedding_size, hidden_size).to(device)  
 criterion_rating = nn.MSELoss()  
 criterion_liked = nn.BCELoss()  
 optimizer = optim.Adam(model.parameters(), lr=0.001)  
 train_rating_losses, train_liked_losses = [], []  
 eval_rating_losses, eval_liked_losses = [], []  
 epochs = 10  
   
 # used for loss normalization  
 initial_loss_rating = None  
 initial_loss_liked = None  
   
 for epoch in range(epochs):  
     model.train()  
     running_loss_rating = 0.0  
     running_loss_liked = 0.0  
       
     for dense_features, labels in train_loader:  
         optimizer.zero_grad()  
         dense_features = dense_features.to(device)  
         labels = labels.to(device)  
           
         rating_pred, liked_pred = model(dense_features)  
         rating_target = labels[:, 0].unsqueeze(1)  
         liked_target = labels[:, 1].unsqueeze(1)  
           
         loss_rating = criterion_rating(rating_pred, rating_target)  
         loss_liked = criterion_liked(liked_pred, liked_target)  
   
         # Set initial losses  
         if initial_loss_rating is None:  
             initial_loss_rating = loss_rating.item()  
         if initial_loss_liked is None:  
             initial_loss_liked = loss_liked.item()  
           
         # Normalize losses  
         loss = (loss_rating / initial_loss_rating) + (loss_liked / initial_loss_liked)  
           
         loss.backward()  
         optimizer.step()  
           
         running_loss_rating += loss_rating.item()  
         running_loss_liked += loss_liked.item()  
       
     train_rating_losses.append(running_loss_rating / len(train_loader))  
     train_liked_losses.append(running_loss_liked / len(train_loader))  
       
     model.eval()  
     eval_loss_rating = 0.0  
     eval_loss_liked = 0.0  
       
     with torch.no_grad():  
         for dense_features, labels in test_loader:  
             dense_features = dense_features.to(device)  
             labels = labels.to(device)  
               
             rating_pred, liked_pred = model(dense_features)  
             rating_target = labels[:, 0].unsqueeze(1)  
             liked_target = labels[:, 1].unsqueeze(1)  
               
             loss_rating = criterion_rating(rating_pred, rating_target)  
             loss_liked = criterion_liked(liked_pred, liked_target)  
               
             eval_loss_rating += loss_rating.item()  
             eval_loss_liked += loss_liked.item()  
       
     eval_rating_losses.append(eval_loss_rating / len(test_loader))  
     eval_liked_losses.append(eval_loss_liked / len(test_loader))  
     print(f'Epoch {epoch+1}, Train Rating Loss: {train_rating_losses[-1]}, Train Liked Loss: {train_liked_losses[-1]}, Eval Rating Loss: {eval_rating_losses[-1]}, Eval Liked Loss: {eval_liked_losses[-1]}')  
 # Plotting losses  
 plt.figure(figsize=(14, 6))  
 plt.subplot(1, 2, 1)  
 plt.plot(train_rating_losses, label='Train Rating Loss')  
 plt.plot(eval_rating_losses, label='Eval Rating Loss')  
 plt.xlabel('Epoch')  
 plt.ylabel('Loss')  
 plt.title('Rating Loss')  
 plt.legend()  
 plt.subplot(1, 2, 2)  
 plt.plot(train_liked_losses, label='Train Liked Loss')  
 plt.plot(eval_liked_losses, label='Eval Liked Loss')  
 plt.xlabel('Epoch')  
 plt.ylabel('Loss')  
 plt.title('Liked Loss')  
 plt.legend()  
 plt.tight_layout()  
 plt.show()

還可以通過利用 Tensorboard 監(jiān)控訓(xùn)練的過程

from torch.utils.tensorboard import SummaryWriter  
 # Check if GPU is available  
 device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  
 print(f"Using device: {device}")  
 # Model and Training Setup  
 embedding_size = 16  
 hidden_size = 32  
 n_users = len(user_encoder.classes_)  
 n_movies = len(movie_encoder.classes_)  
 model = MultiTaskMovieLensModel(n_users, n_movies, embedding_size, hidden_size).to(device)  
 criterion_rating = nn.MSELoss()  
 criterion_liked = nn.BCELoss()  
 optimizer = optim.Adam(model.parameters(), lr=0.001)  
 epochs = 10  
   
 # used for loss normalization  
 initial_loss_rating = None  
 initial_loss_liked = None  
   
 # TensorBoard setup  
 writer = SummaryWriter(log_dir='runs/multitask_movie_lens')  
   
 # Training Loop with TensorBoard Logging  
 for epoch in range(epochs):  
     model.train()  
     running_loss_rating = 0.0  
     running_loss_liked = 0.0  
     for batch_idx, (dense_features, labels) in enumerate(train_loader):  
         # Move data to GPU  
         dense_features = dense_features.to(device)  
         labels = labels.to(device)  
           
         optimizer.zero_grad()  
           
         rating_pred, liked_pred = model(dense_features)  
         rating_target = labels[:, 0].unsqueeze(1)  
         liked_target = labels[:, 1].unsqueeze(1)  
           
         loss_rating = criterion_rating(rating_pred, rating_target)  
         loss_liked = criterion_liked(liked_pred, liked_target)  
   
         # Set initial losses  
         if initial_loss_rating is None:  
             initial_loss_rating = loss_rating.item()  
         if initial_loss_liked is None:  
             initial_loss_liked = loss_liked.item()  
           
         # Normalize losses  
         loss = (loss_rating / initial_loss_rating) + (loss_liked / initial_loss_liked)  
           
         loss.backward()  
         optimizer.step()  
           
         running_loss_rating += loss_rating.item()  
         running_loss_liked += loss_liked.item()  
           
         # Log loss to TensorBoard  
         writer.add_scalar('Loss/Train_Rating', loss_rating.item(), epoch * len(train_loader) + batch_idx)  
         writer.add_scalar('Loss/Train_Liked', loss_liked.item(), epoch * len(train_loader) + batch_idx)  
       
     print(f'Epoch {epoch+1}/{epochs}, Train Rating Loss: {running_loss_rating / len(train_loader)}, Train Liked Loss: {running_loss_liked / len(train_loader)}')  
       
     # Evaluate on the test set  
     model.eval()  
     eval_loss_rating = 0.0  
     eval_loss_liked = 0.0  
     with torch.no_grad():  
         for dense_features, labels in test_loader:  
             # Move data to GPU  
             dense_features = dense_features.to(device)  
             labels = labels.to(device)  
               
             rating_pred, liked_pred = model(dense_features)  
             rating_target = labels[:, 0].unsqueeze(1)  
             liked_target = labels[:, 1].unsqueeze(1)  
               
             loss_rating = criterion_rating(rating_pred, rating_target)  
             loss_liked = criterion_liked(liked_pred, liked_target)  
             eval_loss_rating += loss_rating.item()  
             eval_loss_liked += loss_liked.item()  
       
     eval_loss_avg_rating = eval_loss_rating / len(test_loader)  
     eval_loss_avg_liked = eval_loss_liked / len(test_loader)  
     print(f'Epoch {epoch+1}/{epochs}, Eval Rating Loss: {eval_loss_avg_rating}, Eval Liked Loss: {eval_loss_avg_liked}')  
       
     # Log evaluation loss to TensorBoard  
     writer.add_scalar('Loss/Eval_Rating', eval_loss_avg_rating, epoch)  
     writer.add_scalar('Loss/Eval_Liked', eval_loss_avg_liked, epoch)  
 # Close the TensorBoard writer  
 writer.close()

我們在同一目錄下運行 TensorBoard 來啟動服務(wù)器,并在網(wǎng)絡(luò)瀏覽器中檢查訓(xùn)練和評估曲線。在以下 bash 命令中,將 runs/mutlitask_movie_lens 替換為包含事件文件(日志)的目錄路徑。

(base) $ tensorboard --logdir=runs/multitask_movie_lens
TensorFlow installation not found - running with reduced feature set.

運行結(jié)果如下:

NOTE: Using experimental fast data loading logic. To disable, pass  
    "--load_fast=false" and report issues on GitHub. More details:  
    <https://github.com/tensorflow/tensorboard/issues/4784>
 Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all  
 TensorBoard 2.12.0 at <http://localhost:6006/> (Press CTRL+C to quit)

Tensorboard 損失曲線視圖如上所示

5.推理

在訓(xùn)練完成后要使用 torch.save 函數(shù)將模型保存到磁盤。這個函數(shù)允許你保存模型的狀態(tài)字典,其中包含模型的所有參數(shù)和緩沖區(qū)。保存的文件通常使用 .pth 或 .pt 擴展名。

import torch
torch.save(model.state_dict(), "model.pth")

狀態(tài)字典包含所有模型參數(shù)(權(quán)重和偏置),當想要將模型加載回代碼中時,可以使用以下步驟:

# Initialize the model (make sure the architecture matches the saved model)  
model = MultiTaskMovieLensModel(n_users, n_movies, embedding_size, hidden_size)  
  
# Load the saved state dictionary into the model  
model.load_state_dict(torch.load("model.pth"))  
  
# Set the model to evaluation mode (important for inference)  
model.eval()

為了在一些未見過的數(shù)據(jù)上評估模型,可以對單個用戶-電影對進行預(yù)測,并將它們與實際值進行比較。

def predict_and_compare(user_id, movie_id, model, user_encoder, movie_encoder, train_dataset, test_dataset):  
    user_idx = user_encoder.transform([user_id])[0]  
    movie_idx = movie_encoder.transform([movie_id])[0]  
    example_user = torch.tensor([[user_idx]], dtype=torch.long)  
    example_movie = torch.tensor([[movie_idx]], dtype=torch.long)  
    example_dense_features = torch.cat((example_user, example_movie), dim=1)  
    model.eval()  
    with torch.no_grad():  
        rating_pred, liked_pred = model(example_dense_features)  
        predicted_rating = rating_pred.item()  
        predicted_liked = liked_pred.item()  
    actual_row = train_dataset.data[(train_dataset.data['userId'] == user_id) & (train_dataset.data['movieId'] == movie_id)]  
    if actual_row.empty:  
        actual_row = test_dataset.data[(test_dataset.data['userId'] == user_id) & (test_dataset.data['movieId'] == movie_id)]  
    if not actual_row.empty:  
        actual_rating = actual_row['rating'].values[0]  
        actual_liked = actual_row['liked'].values[0]  
        return {  
            'User ID': user_id,  
            'Movie ID': movie_id,  
            'Predicted Rating': round(predicted_rating, 2),  
            'Actual Rating': actual_rating,  
            'Predicted Liked': 'Yes' if predicted_liked >= 0.5 else 'No',  
            'Actual Liked': 'Yes' if actual_liked == 1 else 'No'  
        }  
    else:  
        return None  
example_pairs = test_dataset.data.sample(n=5)  
results = []  
for _, row in example_pairs.iterrows():  
    user_id = row['userId']  
    movie_id = row['movieId']  
    result = predict_and_compare(user_id, movie_id, model, user_encoder, movie_encoder, train_dataset, test_dataset)  
    if result:  
        results.append(result)  
results_df = pd.DataFrame(results)  
results_df.head()

6.使用 Ray Serve 部署模型

最后就是將模型部署為一個服務(wù),使其可以通過 API 訪問,這里使用使用 Ray Serve。

使用 Ray Serve是因為它可以從單機無縫擴展到大型集群,可以處理不斷增加的負載。Ray Serve 還集成了 Ray 的儀表板,為監(jiān)控部署的健康狀況、性能和資源使用提供了用戶友好的界面。

步驟 1:加載訓(xùn)練好的模型

# Load your trained model (assuming it's saved as 'model.pth')  
n_users = 1000  # 示例值,替換為實際用戶數(shù)  
n_movies = 1000  # 示例值,替換為實際電影數(shù)  
embedding_size = 16  
hidden_size = 32  
model = MultiTaskMovieLensModel(n_users, n_movies, embedding_size, hidden_size)  
model.load_state_dict(torch.load("model.pth"))  
model.eval()

步驟 2:定義模型服務(wù)類

import ray  
from ray import serve  
@serve.deployment  
class ModelServeDeployment:  
    def __init__(self, model):  
        self.model = model  
        self.model.eval()  
    async def __call__(self, request):  
        json_input = await request.json()  
        user_id = torch.tensor([json_input["user_id"]])  
        movie_id = torch.tensor([json_input["movie_id"]])  
        with torch.no_grad():  
            rating_pred, liked_pred = self.model(user_id, movie_id)  
        return {  
            "rating_prediction": rating_pred.item(),  
            "liked_prediction": liked_pred.item()  
        }

步驟 3:初始化 Ray 服務(wù)器

# 初始化 Ray 和 Ray Serve  
ray.init()  
serve.start()  
# 部署模型  
model_deployment = ModelServeDeployment.bind(model)  
serve.run(model_deployment)

現(xiàn)在應(yīng)該能夠在 localhost:8265 看到 ray 服務(wù)器

步驟 4:查詢模型

最后就是測試 API 了。運行以下代碼行時,應(yīng)該可以看到一個響應(yīng),其中包含查詢用戶和電影的評分和喜歡預(yù)測

import requests  
  
# 定義服務(wù)器地址(Ray Serve 默認為 http://127.0.0.1:8000)  
url = "http://127.0.0.1:8000/ModelServeDeployment"  
# 示例輸入  
data = {  
    "user_id": 123,  # 替換為實際用戶 ID  
    "movie_id": 456  # 替換為實際電影 ID  
}  
# 向模型服務(wù)器發(fā)送 POST 請求  
response = requests.post(url, json=data)  
# 打印模型的響應(yīng)  
print(response.json())

就是這樣,我們剛剛訓(xùn)練并部署了一個多任務(wù)多標簽?zāi)P停?/p>

責任編輯:華軒 來源: DeepHub IMBA
相關(guān)推薦

2022-01-29 21:54:58

電商用戶數(shù)據(jù)

2010-09-16 14:08:13

無線雙網(wǎng)

2016-04-27 09:49:16

用戶模型產(chǎn)品總結(jié)

2017-10-18 09:48:13

深度學(xué)習(xí)TensorFlow入門篇

2021-07-14 09:00:00

JavaFX開發(fā)應(yīng)用

2011-05-03 15:59:00

黑盒打印機

2011-01-10 14:41:26

2025-05-07 00:31:30

2020-11-27 07:38:43

MongoDB

2018-05-16 15:46:06

Python網(wǎng)絡(luò)爬蟲PhantomJS

2017-02-09 18:50:42

深度學(xué)習(xí)機器計算機

2023-04-26 12:46:43

DockerSpringKubernetes

2022-12-07 08:42:35

2022-03-14 14:47:21

HarmonyOS操作系統(tǒng)鴻蒙

2022-07-27 08:16:22

搜索引擎Lucene

2022-01-08 20:04:20

攔截系統(tǒng)調(diào)用

2011-02-22 13:46:27

微軟SQL.NET

2021-02-26 11:54:38

MyBatis 插件接口

2021-12-28 08:38:26

Linux 中斷喚醒系統(tǒng)Linux 系統(tǒng)

2019-07-06 10:18:07

人工智能
點贊
收藏

51CTO技術(shù)棧公眾號

亚洲www色| 久久这里只有精品免费| 日韩制服一区| 亚洲日本一区二区三区| 国产精品日韩一区二区三区 | 色先锋久久影院av| 欧洲av一区二区嗯嗯嗯啊| 国产免费色视频| 日本韩国免费观看| 蜜桃久久久久久| 色在人av网站天堂精品| 中文字幕被公侵犯的漂亮人妻| 欧美成人家庭影院| 天天爽夜夜爽夜夜爽精品视频| 日韩在线三区| 男人的天堂a在线| 麻豆精品一区二区三区| 97人人做人人爱| √天堂中文官网8在线| 丝袜连裤袜欧美激情日韩| 欧美久久一二区| 黄色动漫在线免费看| 看黄网站在线| 久久嫩草精品久久久精品一| 欧美激情精品| 日韩黄色免费网站| 久久国产精品视频| av中文字幕免费观看| 亚洲精品福利| 欧美色成人综合| 国产 福利 在线| 青青青草视频在线| 中文字幕亚洲一区二区av在线| 精品国产乱码久久久久久久软件| 91无套直看片红桃| 日韩av网站免费在线| 97视频在线观看亚洲| 欧美卡一卡二卡三| 欧美韩日高清| 中文一区二区视频| 国产在线观看h| 久久a级毛片毛片免费观看| 制服丝袜av成人在线看| 91小视频网站| 写真福利精品福利在线观看| 日韩欧美成人网| 黄色片网址在线观看| 金瓶狂野欧美性猛交xxxx | 懂色一区二区三区av片| 国产一区二区在线视频观看| 奇米精品一区二区三区四区 | 亚洲欧洲成视频免费观看| 国产一线在线观看| 国产精品流白浆在线观看| 欧美成人女星排名| 日韩大尺度视频| 一区二区三区亚洲变态调教大结局| 666欧美在线视频| 亚洲三级在线观看视频| 小说区图片区亚洲| 69精品人人人人| 欧美精品色视频| 日韩一区二区三区精品| 精品黑人一区二区三区久久 | 99精品在免费线中文字幕网站一区| 777奇米成人网| 99热这里只有精品2| 日韩一区二区三区色| 337p日本欧洲亚洲大胆色噜噜| 99免费观看视频| 国产精品超碰| 日韩精品亚洲视频| 免费黄色片网站| 欧美国产偷国产精品三区| 久久在线视频在线| 精品视频久久久久| 羞羞答答国产精品www一本| 日本亚洲精品在线观看| 中文字幕乱码一区二区 | 一本色道久久综合亚洲91| 日韩亚洲在线视频| 97久久中文字幕| 欧美不卡视频一区| 免费在线观看你懂的| 成人久久综合| 久久99热精品| 欧美日韩乱国产| 日本美女一区二区三区视频| 91视频免费在线| 少妇一级淫片免费看| 日本一区二区三区在线不卡| 男女啪啪的视频| zzzwww在线看片免费| 在线观看一区二区精品视频| 在线视频日韩欧美| 日韩高清一级| 免费91麻豆精品国产自产在线观看| 国产乡下妇女做爰| 视频一区二区中文字幕| 91九色单男在线观看| 少妇精品高潮欲妇又嫩中文字幕| 国产精品天美传媒沈樵| 人人妻人人澡人人爽欧美一区双 | 国产在线久久久| 蜜桃久久一区二区三区| 亚洲国产成人午夜在线一区| www成人免费| 国产日本久久| 日韩av最新在线| 538精品在线视频| 首页国产欧美日韩丝袜| 成人午夜电影在线播放| 成人欧美亚洲| 狠狠躁夜夜躁人人躁婷婷91| 黄色片免费网址| 精品国产乱码久久久久久果冻传媒| 精品中文字幕在线2019| 国产精品传媒在线观看| 成人午夜伦理影院| 青青草原国产免费| 国产综合色区在线观看| 亚洲国产高清自拍| 一区二区视频免费看| 奇米888四色在线精品| 老牛影视免费一区二区| 日本高清在线观看| 欧美欧美欧美欧美| 亚洲精品一区二区三区影院忠贞| 日韩五码在线| 国产精成人品localhost| 日本电影全部在线观看网站视频| 一本大道久久a久久综合婷婷| 最新国产精品自拍| 欧美一区精品| 91九色国产在线| 麻豆网站在线看| 欧美视频一区在线观看| 国产人妻大战黑人20p| 亚洲影院免费| 久久这里精品国产99丫e6| 国产蜜臀一区二区打屁股调教| 5月丁香婷婷综合| 三级黄色在线观看| 久久99热国产| 亚洲一区二区自拍偷拍| 福利一区二区| 中文字幕亚洲在线| 在线观看中文字幕av| 国产欧美1区2区3区| 老熟妇仑乱视频一区二区| 五月国产精品| 欧洲日本亚洲国产区| 五月婷婷久久久| 欧美日韩亚洲一区二区三区| 朝桐光av一区二区三区| 国产农村妇女毛片精品久久莱园子 | 亚洲精品一区国产精品| 岛国一区二区| 久久伊人91精品综合网站| 999免费视频| 一区二区三区在线观看欧美| 亚洲性图第一页| 在线日韩电影| 欧美一区二区三区成人久久片| 日本精品不卡| 伊人伊成久久人综合网站| 中文字幕观看视频| 亚洲欧美韩国综合色| 18深夜在线观看免费视频| 欧美日韩精品一本二本三本| 成人综合色站| 中文在线а√在线8| 国产一区二区三区在线观看网站 | 狂野欧美性猛交xxxx巴西| 视频一区二区三| 91精品麻豆| 久久免费观看视频| 视频二区在线| 欧美偷拍一区二区| 欧美精品videos极品| a亚洲天堂av| 国产精品久久久久9999小说| 99久久婷婷这里只有精品| 99久久一区三区四区免费| 岛国av在线网站| 中文字幕无线精品亚洲乱码一区| 91九色蝌蚪91por成人| 亚洲最大成人综合| 五月天综合视频| 国产风韵犹存在线视精品| 欧美 日韩 亚洲 一区| 欧美亚洲在线日韩| 亚洲精品欧美极品| 欧美色网一区| 欧美尺度大的性做爰视频| 日韩av地址| 91精品国产欧美一区二区18| 制服.丝袜.亚洲.中文.综合懂色| 国产精品久久久久一区二区三区 | 国产精品成人自拍| 国产精品入口尤物| av中文资源在线资源免费观看| 一个人看的www久久| 亚洲免费国产视频| 欧美日韩一区二区三区在线| 日本在线免费观看| 中文字幕在线一区| 中日韩精品一区二区三区| 国产酒店精品激情| 日韩欧美黄色大片| 亚洲国产网站| 91社在线播放| japanese国产精品| 精品视频第一区| 9999在线精品视频| 国产精品久久一区主播| 爱啪啪综合导航| 九九热精品视频在线播放| 99riav在线| 亚洲欧美精品在线| 成人激情四射网| 911国产精品| 久久精品99北条麻妃| 精品欧美国产一区二区三区| 欧美日韩一级在线观看| 中文字幕在线观看不卡| mm131丰满少妇人体欣赏图| 成人激情小说网站| 91人妻一区二区三区| 麻豆成人综合网| 国产精品久久久久9999小说| 亚洲欧美卡通另类91av| 国自产拍偷拍精品啪啪一区二区| 欧美激情亚洲| 国产精品12p| 国产韩日影视精品| 一本一道久久a久久综合精品| 欧洲福利电影| 亚洲欧洲日产国产综合网| 不卡的一区二区| 久久国产三级精品| 国产精品久久久毛片| 老妇喷水一区二区三区| av黄色在线网站| 99在线|亚洲一区二区| 免费一级特黄毛片| 亚洲激情偷拍| 久久亚洲中文字幕无码| 亚洲午夜在线| 成人免费视频91| 亚洲三级影院| 国产精品后入内射日本在线观看| 激情综合网址| 国产美女在线一区| 亚洲久久一区| 波多野结衣家庭教师在线| 国产一区二区三区成人欧美日韩在线观看| 黄色一级视频在线播放| 夜夜爽av福利精品导航| 日本精品免费在线观看| 噜噜噜躁狠狠躁狠狠精品视频| 92看片淫黄大片一级| 丝袜a∨在线一区二区三区不卡 | 毛片电影在线| 日本91av在线播放| 成人日韩av| 成人在线小视频| 中文字幕一区二区三区四区久久| 成人综合av网| 久久99国产精品视频| 亚洲一卡二卡区| 国产精品mm| 亚洲熟女乱色一区二区三区| 日韩黄色免费电影| 99久久99精品| 99国产精品久久| 少妇精品无码一区二区免费视频| 国产精品久久久久一区二区三区| 久草中文在线视频| 一本一本久久a久久精品综合麻豆| 少妇又紧又色又爽又刺激视频| 91精品国产综合久久福利软件 | 不卡的av电影| 阿v天堂2014| 亚洲精品欧美激情| 国产美女激情视频| 欧美丰满一区二区免费视频| 狠狠躁日日躁夜夜躁av| 亚洲视频在线观看| 69xxx在线| 日本精品视频在线观看| 91精品视频一区二区| 久久久久无码国产精品一区| 欧美激情黄色片| 精品人妻少妇一区二区| 蜜臀av国产精品久久久久| 国产欧美视频一区| 国产精品色呦呦| 日韩免费在线视频观看| 欧美二区三区的天堂| 亚洲欧洲国产综合| 欧美精品在线观看| 456成人影院在线观看| 国产精品v欧美精品v日韩精品 | 白白色亚洲国产精品| 亚洲aaa视频| 欧美午夜xxx| 精品欧美在线观看| 中文字幕日韩视频| 国产精品一区二区日韩| 91免费高清视频| 精品久久精品| 免费成人在线视频网站| 国产在线日韩欧美| 免费视频91蜜桃| 精品国产999| 亚洲国产一二三区| 色悠悠久久久久| 成人看片网页| 久久精品第九区免费观看| 欧美99久久| 亚洲三级在线观看视频| 中文字幕乱码日本亚洲一区二区| 精品久久免费视频| 精品久久一二三区| 97caopor国产在线视频| 国产精品亚洲视频在线观看| 亚瑟一区二区三区四区| 又大又硬又爽免费视频| 国产麻豆欧美日韩一区| 日韩av毛片在线观看| 欧洲色大大久久| 精品成人一区二区三区免费视频| 久久免费视频网站| 97品白浆高清久久久久久| 国产又黄又爽免费视频| 久久99久久久久久久久久久| youjizz亚洲女人| 在线免费观看日韩欧美| 欧美69xxxxx| 国产精品99久久久久久久久| 天天躁日日躁狠狠躁欧美| 国产一线二线三线女| 成人精品视频.| 精品一级少妇久久久久久久| 日韩视频免费观看高清完整版 | 波多野结衣中文字幕在线播放| 国产精品久久久久久户外露出| 精品国产www| 中文字幕亚洲欧美一区二区三区 | 国产99在线免费| 欧美午夜在线| 黄色av网址在线观看| 五月综合激情日本mⅴ| 亚洲av激情无码专区在线播放| 26uuu久久噜噜噜噜| 亚洲美女久久| 国产免费视频传媒| 亚洲欧洲成人av每日更新| 国产日本精品视频| 欧美精品激情在线| 欧美中文一区| 精品久久久噜噜噜噜久久图片| 中文字幕av一区 二区| 一区二区三区播放| 色综合五月天导航| 久久久免费毛片| caoporn超碰97| 亚洲欧洲在线观看av| www.色视频| 欧美一区二区三区四区在线| 免费黄色成人| 日韩av.com| 亚洲国产wwwccc36天堂| 欧洲免费在线视频| 成人在线精品视频| 亚洲精品孕妇| 一区二区三区在线观看免费视频| 777午夜精品视频在线播放| 欧美videossex| 日本一区二区视频| 国产老肥熟一区二区三区| 亚洲国产精品午夜在线观看| 亚洲视频第一页| 老司机亚洲精品一区二区| 欧美深夜福利视频| 国产精品区一区二区三区| 超碰在线播放97| 国产成人精品久久二区二区| 综合国产精品| 伊人网在线视频观看| 91精品婷婷国产综合久久性色| 91老司机福利在线| 亚洲欧洲久久| 顶级嫩模精品视频在线看| 久久久久久无码精品大片| 精品少妇v888av| 日本一本不卡| 变态另类丨国产精品| 欧美日韩免费高清一区色橹橹|