調制信號識別系列 (一):基準模型

調制信號識別系列 (一):基準模型

說明:本文包含對CNN和CNN+LSTM基準模型的復現,模型架構參考下述兩篇文章

文章目錄

  • 調制信號識別系列 (一):基準模型
    • 一、論文
      • 1、DL-PR: Generalized automatic modulation classification method based on deep learning with priori regularization
      • 2、A Deep Learning Approach for Modulation Recognition via Exploiting Temporal Correlations
    • 二、流程
      • 1、數據加載
      • 2、訓練測試
      • 3、可視化
    • 三、模型
      • 1、CNN
      • 2、CNN+LSTM(DL-PR)
      • 3、CNN+LSTM
    • 四、對比
      • 1、論文1
      • 2、論文2
    • 五、總結

一、論文

1、DL-PR: Generalized automatic modulation classification method based on deep learning with priori regularization

  • https://www.sciencedirect.com/science/article/pii/S095219762300266X

image-20240707105742936

image-20240706174502716

2、A Deep Learning Approach for Modulation Recognition via Exploiting Temporal Correlations

  • 2018 IEEE 19th International Workshop on Signal Processing Advances in Wireless Communications (SPAWC)

  • https://ieeexplore.ieee.org/abstract/document/8445938

image-20240707114714838

Note that before each convolutional layer, we use the zero-padding method to control the spatial size of the output volumes. Specifically, we pad the input volume with two zeros around the border, thus the output volume of the second convolutional layer is of size 32 × 132. We then take 32 as the dimensionality of the input and 132 as the time steps in LSTM layer. Dropout method is also used to prevent the neural network from overfitting. Compared to architecture in [12], we can see that we replace the third dense fully-connected layer with a LSTM layer. Our simulations suggest that this replacement not only reduces the number of parameters by an order of magnitude, but also leads to a significant performance improvement.

請注意,在每個卷積層之前,我們使用零填充方法來控制輸出卷的空間大小。具體來說,我們在輸入量的邊界周圍填充兩個零,因此第二個卷積層的輸出量的大小為 32 × 132。然后我們將 32 作為輸入的維度,將 132 作為 LSTM 層的時間步長。 Dropout方法也用于防止神經網絡過擬合。與[12]中的架構相比,我們可以看到我們用 LSTM 層替換了第三個密集全連接層。我們的模擬表明,這種替換不僅將參數數量減少了一個數量級,而且還帶來了顯著的性能改進。

二、流程

1、數據加載

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset, random_split
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
from torchsummary import summary
# 加載數據
csv_file_path = 'snr_data/output_data_snr_6.csv'
data_frame = pd.read_csv(csv_file_path)# 提取前256列數據并轉換為張量
vectors = torch.tensor(data_frame.iloc[:, :256].values, dtype=torch.float32)# 將256維向量轉換為2x128的矩陣形式
vectors = vectors.view(-1, 2, 128)# 劃分訓練集和測試集索引
train_size = int(0.8 * len(vectors))
test_size = len(vectors) - train_size
train_indices, test_indices = random_split(range(len(vectors)), [train_size, test_size])# 使用訓練集的統計量進行歸一化
train_vectors = vectors[train_indices]# 對IQ分量分別進行歸一化
train_mean_I = train_vectors[:, 0, :].mean(dim=0, keepdim=True)
train_std_I = train_vectors[:, 0, :].std(dim=0, keepdim=True)train_mean_Q = train_vectors[:, 1, :].mean(dim=0, keepdim=True)
train_std_Q = train_vectors[:, 1, :].std(dim=0, keepdim=True)# 歸一化整個數據集
vectors[:, 0, :] = (vectors[:, 0, :] - train_mean_I) / train_std_I
vectors[:, 1, :] = (vectors[:, 1, :] - train_mean_Q) / train_std_Q# 提取Mod_Type列并轉換為數值標簽
mod_types = data_frame['Mod_Type'].astype('category').cat.codes.values
labels = torch.tensor(mod_types, dtype=torch.long)# 創建TensorDataset
dataset = TensorDataset(vectors, labels)# 創建訓練集和測試集
train_dataset = TensorDataset(vectors[train_indices], labels[train_indices])
test_dataset = TensorDataset(vectors[test_indices], labels[test_indices])# 創建DataLoader
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
# 替換模型架構

2、訓練測試

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
num_epochs = 50
train_losses = []
test_losses = []
train_accuracies = []
test_accuracies = []def calculate_accuracy(outputs, labels):_, predicted = torch.max(outputs, 1)total = labels.size(0)correct = (predicted == labels).sum().item()return correct / totalfor epoch in range(num_epochs):# 訓練階段model.train()running_loss = 0.0correct = 0total = 0for inputs, labels in train_loader:inputs = inputs.to(device)labels = labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()correct += (outputs.argmax(1) == labels).sum().item()total += labels.size(0)train_loss = running_loss / len(train_loader)train_accuracy = correct / totaltrain_losses.append(train_loss)train_accuracies.append(train_accuracy)# 測試階段model.eval()running_loss = 0.0correct = 0total = 0with torch.no_grad():for inputs, labels in test_loader:inputs = inputs.to(device)labels = labels.to(device)outputs = model(inputs)loss = criterion(outputs, labels)running_loss += loss.item()correct += (outputs.argmax(1) == labels).sum().item()total += labels.size(0)test_loss = running_loss / len(test_loader)test_accuracy = correct / totaltest_losses.append(test_loss)test_accuracies.append(test_accuracy)print(f"Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")print("Training complete.")

3、可視化

epochs = range(1, num_epochs + 1)plt.figure(figsize=(12, 5))# 繪制損失圖像
plt.subplot(1, 2, 1)
plt.plot(epochs, train_losses, label='Train Loss')
plt.plot(epochs, test_losses, label='Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.title('Loss vs. Epochs')# 繪制準確率圖像
plt.subplot(1, 2, 2)
plt.plot(epochs, train_accuracies, label='Train Accuracy')
plt.plot(epochs, test_accuracies, label='Test Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.title('Accuracy vs. Epochs')plt.show()

三、模型

說明:下述模型均在SNR=6dB RadioML2016.10a數據集下的實驗結果,僅使用原始的IQ分量信息,未使用數據增強,也未進行調參

1、CNN

class CNNModel(nn.Module):def __init__(self):super(CNNModel, self).__init__()self.conv1 = nn.Conv2d(1, 64, (1, 4), stride=1)self.conv2 = nn.Conv2d(64, 64, (1, 2), stride=1)self.pool1 = nn.MaxPool2d((1, 2))self.conv3 = nn.Conv2d(64, 128, (1, 2), stride=1)self.conv4 = nn.Conv2d(128, 128, (2, 2), stride=1)self.pool2 = nn.MaxPool2d((1, 2))self.conv5 = nn.Conv2d(128, 256, (1, 2), stride=1)self.conv6 = nn.Conv2d(256, 256, (1, 2), stride=1)self.fc1 = nn.Linear(256 * 1 * 28, 512)self.fc2 = nn.Linear(512, 128)self.fc3 = nn.Linear(128, 11)def forward(self, x):x = x.unsqueeze(1)  # 添加通道維度x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = self.pool1(x)x = torch.relu(self.conv3(x))x = torch.relu(self.conv4(x))x = self.pool2(x)x = torch.relu(self.conv5(x))x = torch.relu(self.conv6(x))x = x.view(x.size(0), -1)x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return xmodel = CNNModel()
summary(model, (2, 128))

image-20240707115545394

----------------------------------------------------------------Layer (type)               Output Shape         Param #
================================================================Conv2d-1           [-1, 64, 2, 125]             320Conv2d-2           [-1, 64, 2, 124]           8,256MaxPool2d-3            [-1, 64, 2, 62]               0Conv2d-4           [-1, 128, 2, 61]          16,512Conv2d-5           [-1, 128, 1, 60]          65,664MaxPool2d-6           [-1, 128, 1, 30]               0Conv2d-7           [-1, 256, 1, 29]          65,792Conv2d-8           [-1, 256, 1, 28]         131,328Linear-9                  [-1, 512]       3,670,528Linear-10                  [-1, 128]          65,664Linear-11                   [-1, 11]           1,419
================================================================
Total params: 4,025,483
Trainable params: 4,025,483
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.63
Params size (MB): 15.36
Estimated Total Size (MB): 15.98

image-20240707115320324

image-20240707115331410

2、CNN+LSTM(DL-PR)

import torch
import torch.nn as nnclass CNNLSTMModel(nn.Module):def __init__(self):super(CNNLSTMModel, self).__init__()self.conv1 = nn.Conv2d(1, 32, (2, 3), stride=1, padding=(0,1))  # Adjusted input channels and filtersself.conv2 = nn.Conv2d(32, 32, (1, 3), stride=1, padding=(0,1))self.pool1 = nn.MaxPool2d((1, 2))self.conv3 = nn.Conv2d(32, 64, (1, 3), stride=1, padding=(0,1))self.conv4 = nn.Conv2d(64, 64, (1, 3), stride=1, padding=(0,1))self.pool2 = nn.MaxPool2d((1, 2))self.conv5 = nn.Conv2d(64, 128, (1, 3), stride=1, padding=(0,1))self.conv6 = nn.Conv2d(128, 128, (1, 3), stride=1, padding=(0,1))self.pool3 = nn.MaxPool2d((1, 2))self.lstm = nn.LSTM(128, 32, batch_first=True)  # Adjusted input size and LSTM hidden sizeself.fc1 = nn.Linear(32, 128)self.fc2 = nn.Linear(128, 11)def forward(self, x):#print("x:",x.shape)if x.dim() == 3:x = x.unsqueeze(1)  # 假設x的形狀是[2, 128], 這將改變它為[1, 2, 128]#print("x.unsqueeze(0):",x.shape)x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = self.pool1(x)x = torch.relu(self.conv3(x))x = torch.relu(self.conv4(x))x = self.pool2(x)x = torch.relu(self.conv5(x))x = torch.relu(self.conv6(x))x = self.pool3(x)# Prepare input for LSTMx = x.view(x.size(0), 16, 128)  # Adjusted view#print(x.shape)x, (hn, cn) = self.lstm(x)x = x[:, -1, :]  # Get the last output of the LSTMx = torch.relu(self.fc1(x))x = self.fc2(x)return xmodel = CNNLSTMModel()
summary(model,input_size=(1, 2, 128))

image-20240707115501540

==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
CNNLSTMModel                             [1, 11]                   --
├─Conv2d: 1-1                            [1, 32, 1, 128]           224
├─Conv2d: 1-2                            [1, 32, 1, 128]           3,104
├─MaxPool2d: 1-3                         [1, 32, 1, 64]            --
├─Conv2d: 1-4                            [1, 64, 1, 64]            6,208
├─Conv2d: 1-5                            [1, 64, 1, 64]            12,352
├─MaxPool2d: 1-6                         [1, 64, 1, 32]            --
├─Conv2d: 1-7                            [1, 128, 1, 32]           24,704
├─Conv2d: 1-8                            [1, 128, 1, 32]           49,280
├─MaxPool2d: 1-9                         [1, 128, 1, 16]           --
├─LSTM: 1-10                             [1, 16, 32]               20,736
├─Linear: 1-11                           [1, 128]                  4,224
├─Linear: 1-12                           [1, 11]                   1,419
==========================================================================================
Total params: 122,251
Trainable params: 122,251
Non-trainable params: 0
Total mult-adds (M): 4.32
==========================================================================================
Input size (MB): 0.00
Forward/backward pass size (MB): 0.20
Params size (MB): 0.49
Estimated Total Size (MB): 0.69
==========================================================================================

image-20240707115432051

image-20240707115443808

3、CNN+LSTM

# 定義結合CNN和LSTM的模型
class CNNLSTMModel(nn.Module):def __init__(self):super(CNNLSTMModel, self).__init__()self.conv1 = nn.Conv2d(1, 64, (1, 4), stride=1)self.conv2 = nn.Conv2d(64, 64, (1, 2), stride=1)self.pool1 = nn.MaxPool2d((1, 2))self.conv3 = nn.Conv2d(64, 128, (1, 2), stride=1)self.conv4 = nn.Conv2d(128, 128, (2, 2), stride=1)self.pool2 = nn.MaxPool2d((1, 2))self.conv5 = nn.Conv2d(128, 256, (1, 2), stride=1)self.conv6 = nn.Conv2d(256, 256, (1, 2), stride=1)self.lstm = nn.LSTM(256, 128, batch_first=True)self.fc1 = nn.Linear(128, 512)self.fc2 = nn.Linear(512, 128)self.fc3 = nn.Linear(128, 11)def forward(self, x):x = x.unsqueeze(1)  # 添加通道維度x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = self.pool1(x)x = torch.relu(self.conv3(x))x = torch.relu(self.conv4(x))x = self.pool2(x)x = torch.relu(self.conv5(x))x = torch.relu(self.conv6(x))# 重新調整x的形狀以適應LSTMx = x.squeeze(2).permute(0, 2, 1)  # 變為(batch_size, 128, 256)# 通過LSTMx, _ = self.lstm(x)# 取最后一個時間步的輸出x = x[:, -1, :]# 全連接層x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return x
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = CNNLSTMModel().to(device)
summary(model,input_size=(1, 2, 128))

image-20240707115530202

==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
CNNLSTMModel                             [1, 11]                   --
├─Conv2d: 1-1                            [1, 64, 2, 125]           320
├─Conv2d: 1-2                            [1, 64, 2, 124]           8,256
├─MaxPool2d: 1-3                         [1, 64, 2, 62]            --
├─Conv2d: 1-4                            [1, 128, 2, 61]           16,512
├─Conv2d: 1-5                            [1, 128, 1, 60]           65,664
├─MaxPool2d: 1-6                         [1, 128, 1, 30]           --
├─Conv2d: 1-7                            [1, 256, 1, 29]           65,792
├─Conv2d: 1-8                            [1, 256, 1, 28]           131,328
├─LSTM: 1-9                              [1, 28, 128]              197,632
├─Linear: 1-10                           [1, 512]                  66,048
├─Linear: 1-11                           [1, 128]                  65,664
├─Linear: 1-12                           [1, 11]                   1,419
==========================================================================================
Total params: 618,635
Trainable params: 618,635
Non-trainable params: 0
Total mult-adds (M): 19.33
==========================================================================================
Input size (MB): 0.00
Forward/backward pass size (MB): 0.59
Params size (MB): 2.47
Estimated Total Size (MB): 3.07
==========================================================================================

image-20240707115355065

image-20240707115406360

四、對比

1、論文1

image-20240707120612759

image-20240707120737565

本文的實驗結果和論文1的結果比較類似,即使without priori regularization

2、論文2

image-20240707120151123

image-20240707120316218

五、總結

  • 對于RadioML2016.10a數據集來說,在信噪比不是特別低的情況下,使用CNN就表現的不錯,在SNR=6dB可達91.82%,但是這里有個小技巧,在卷積過程中,先單獨對IQ分量進行卷積,在convolution 4進行聯合處理,一開始就使用2x2的卷積核效果較差。

image-20240707121309134

  • 實驗結果表明,CNN+LSTM 優于 CNN,但漲幅不多

image-20240707121937158

image-20240707121959303

  • 完整的代碼和數據集在GIthub:https://github.com/daetz-coder/RadioML2016.10a_Benchmark,為了方便使用,IQ分量保存在csv中,且僅提供了SNR=6dB的數據,如果需要更多類型的數據,請參考https://blog.csdn.net/a_student_2020/article/details/139800725

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41228.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41228.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41228.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

軟件架構之操作系統

第 2 章操作系統 本章主要介紹操作系統的基本概念及其形成、發展歷史和主要類型,并指出操作系統的5 大管理功能。掌握操作系統原理的關鍵在于深入理解“一個觀點、兩條線索”。一個觀點是以資源管理的觀點來定義操作系統;兩條線索是指操作系統如何管理計…

【計算機畢業設計】020基于weixin小程序訂餐系統

🙊作者簡介:擁有多年開發工作經驗,分享技術代碼幫助學生學習,獨立完成自己的項目或者畢業設計。 代碼可以私聊博主獲取。🌹贈送計算機畢業設計600個選題excel文件,幫助大學選題。贈送開題報告模板&#xff…

C語言獲取當前時間

一共有兩段代碼&#xff0c;一個是獲取當前時間&#xff0c;一個是獲取到現在的總毫秒數 求關注&#x1f604; 互粉必回 獲取當前時間 #include <stdio.h> #include <time.h> int main() { time_t rawtime; struct tm * timeinfo; char buffer[20]; // 獲取當前…

Linux內核編譯與調試menuos-linux-3.18.6-在ubuntu20.04環境

1 具體操作 下載 linux-3.18.6內核 wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz解壓進入linux-3.18.6文件夾 tar -xvf linux-3.18.6.tar.xz cd linux-3.18.6/編譯 #make x86_64_defconfig # 為x86_64生成配置 #make alldefconfig make i3…

每天一個數據分析題(四百零十)- 主成分

實際應用中&#xff0c;關于主成分數量K的取值&#xff0c;下列說法錯誤的是&#xff08; &#xff09; A. 可以基于碎石圖進行判斷 B. 特征根從大到小排序&#xff0c;通常要求前 K 個特征根都大于 1 C. 通常要求 K 個主成分的累積方差比超過 80% D. 各個主成分之間的方向…

什么是區塊鏈的“智能合約”

區塊鏈的“智能合約”是一種存儲在區塊鏈上的計算機協議&#xff0c;它能夠自動執行合約條款&#xff0c;并在滿足預設條件時自動執行相關操作。智能合約通過編程語言&#xff08;如Solidity&#xff09;編寫&#xff0c;可以在去中心化的環境中運行&#xff0c;無需人工干預。…

spdlog一個非常好用的C++日志庫(七): 源碼分析之異常類spdlog_ex

目錄 1.自定義異常類spdlog_ex 1.1.通用異常 1.2.系統調用異常 1.3.what()函數 2.異常的使用 2.1.拋出異常 2.2.控制異常使用 1.自定義異常類spdlog_ex 標準庫異常類&#xff08;std::exception&#xff09;系列&#xff0c;能滿足大多數使用異常的場景&#xff0c;但對…

100359.統計X和Y頻數相等的子矩陣數量

1.題目描述 給你一個二維字符矩陣 grid&#xff0c;其中 grid[i][j] 可能是 X、Y 或 .&#xff0c;返回滿足以下條件的子矩陣數量&#xff1a; 包含 grid[0][0]X 和 Y 的頻數相等。至少包含一個 X。 示例 1&#xff1a; 輸入&#xff1a; grid [["X","Y",…

Avalonia中的樣式

文章目錄 前言樣式定義代碼切換樣式樣式主題前言 Avalonia的樣式是Styles,與WPF類似。用于在控件之間共享屬性設置用于在控件之間共享屬性設置,樣式由 Selector和屬性組成。 樣式定義 下面定義一個最簡單的樣式 <Window.Styles><Style Selector="TextBlock…

雙 Token 無感刷新機制實現

?作者簡介&#xff1a;熱愛Java后端開發的一名學習者&#xff0c;大家可以跟我一起討論各種問題喔。 &#x1f34e;個人主頁&#xff1a;Hhzzy99 &#x1f34a;個人信條&#xff1a;堅持就是勝利&#xff01; &#x1f49e;當前專欄&#xff1a;項目實踐 &#x1f96d;本文內容…

微信小程序性能與體驗優化

1. 合理的設置可點擊元素的響應區域大小&#xff1b; 比較常見的是頁面的點擊按鈕太小&#xff0c;用戶點擊不到按鈕&#xff0c;這樣用戶體驗很不好。 2. 避免渲染頁面耗時過長&#xff1b; 當頁面渲染時間過長的話&#xff0c;會讓用戶感覺非常卡頓&#xff0c;當出現這種…

密室逃脫——收集版修改測試

一、原版修改 1、導入資源 Unity Learn | 3D Beginner: Complete Project | URP 2、設置Scene 刪除SampleScene&#xff0c;打開UnityTechnologies-3DBeginnerComplete下的MainScene 3、降低音量 (1) 打開Hierarchy面板上的Audio降低音量 (2) 打開Prefabs文件夾&#xf…

lnmp php7 安裝ssh2擴展

安裝ssh2擴展前必須安裝libssh2包 下載地址: wget http://www.libssh2.org/download/libssh2-1.11.0.tar.gzwget http://pecl.php.net/get/ssh2-1.4.tgz &#xff08;這里要換成最新的版本&#xff09; 先安裝 libssh2 再安裝 SSH2: tar -zxvf libssh2-1.11.0.tar.gzcd libss…

若依框架(RuoYi)中實現部門及子部門用戶查詢的SQL邏輯解析

前言 在基于若依框架&#xff08;RuoYi&#xff09;的項目開發中&#xff0c;經常會遇到需要根據部門ID查詢其下屬所有用戶的需求&#xff0c;包括直接隸屬于該部門的用戶以及屬于其子部門的所有用戶。這一需求在組織架構管理、權限分配等場景中尤為常見。本文將深入解析一段典…

【深入理解計算機系統——2信息的表示和處理】

計算機的本質就是二進制&#xff0c;0/1&#xff0c;稱之為bit&#xff08;位&#xff09;&#xff0c;一個位沒有什么意義&#xff0c;當同時擁有多個位&#xff0c;并且加上某種解釋&#xff0c;就可以表示任何有限集合的元素。&#xff08;為什么是有限&#xff1f;因為用bi…

【日志信息管理】管理日志信息的類

日志用于記錄程序的執行記錄包括程序的出錯記錄&#xff0c;程序致命退出原因&#xff0c;程序的正常執行記錄。這樣我們就可以很快的察覺程序的錯誤原因、執行狀況等等&#xff0c;因此管理日志信息是非常重要的。 日志一般由以下部分組合&#xff1a; 日志時間、日志等級、…

Java 基礎--File - IO流(2)

I/O流 定義 數據從硬盤流向內存為輸入流&#xff0c;數據從內存流向硬盤為輸出流。輸入也叫讀取數據&#xff0c;輸出也叫寫出數據。 IO分類 1.按照數據的流向分為&#xff1a;輸入流和輸出流 ①輸入流&#xff1a;把數據從其他設備上讀取到內存中的流 ②輸出流&#xff1…

Qt 基礎組件速學 事件過濾器

學習目標&#xff1a;理解事件過濾器 前置環境 運行環境:qt creator 4.12 學習內容和效果演示&#xff1a; Qt 提供了事件過濾器的機制,允許我們在事件到達目標對象之前對事件進行攔截和處理。這在以下情況下非常有用: 全局事件處理: 我們可以在應用程序級別安裝一個事件過…

工控人最愛的PLC觸摸屏一體機,有多香

PLC觸摸屏一體機是什么 PLC觸摸屏一體機&#xff0c;聽起來可能有點技術化&#xff0c;但簡單來說&#xff0c;它就是一個集成了可編程邏輯控制器&#xff08;PLC&#xff09;和觸摸屏的智能設備。這種設備不僅能夠執行自動化控制任務&#xff0c;還能實時顯示和操作設備狀態&a…

JVM原理(十九):JVM虛擬機內存模型

1. 硬件的效率與一致性 數據不安全的原因&#xff1a;緩存一致性的問題 共享內存多核系統&#xff1a;在多路處理器系統中&#xff0c;每個處理器都有自己的高速緩存&#xff0c;而他們又共享同一主內存。 線程先后執行結果不一致問題&#xff1a;除了增加高速緩存之外&#…