ICEEMDAN-Solar_power-forecast/iceemdan分解 逐步分解.ipynb

12 KiB
Raw Blame History

In [ ]:
from math import sqrt
from numpy import concatenate
from matplotlib import pyplot
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import mean_squared_error
from tensorflow.keras import Sequential

from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import LSTM
from tensorflow.keras.layers import Dropout
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
In [ ]:
# 加载数据
path1 = r"D:\project\小论文1-基于ICEEMDAN分解的时序高维变化的短期光伏功率预测模型\CEEMAN-PosConv1dbiLSTM-LSTM\模型代码流程\data6.csv"#数据所在路径
#我的数据是excel表若是csv文件用pandas的read_csv()函数替换即可。
datas1 = pd.DataFrame(pd.read_csv(path1))
#我只取了data表里的第3、23、16、17、18、19、20、21、27列如果取全部列的话这一行可以去掉
# data1 = datas1.iloc[:,np.r_[3,23,16:22,27]]
data1=datas1.interpolate()
values1 = data1.values
print(data1.head())
print(data1.shape)
In [ ]:
data1
In [ ]:
from PyEMD import EMD
import pandas as pd
import numpy as np

def ICEEMDAN(data, num_siftings=18, Nstd=0.2, NR=100):
    """
    改进的完全集合经验模态分解与自适应噪声ICEEMDAN
    """
    emd = EMD()
    T = len(data)
    std_data = np.std(data)
    
    # 通过添加白噪声获取数据的 IMFs 集合
    E_IMFs = np.zeros((NR, T, num_siftings))
    for r in range(NR):
        wn = np.random.normal(scale=std_data*Nstd, size=T)
        noisy_data = data + wn
        
        # 分解带噪声的数据
        imfs = emd.emd(noisy_data)
        
        # 仅保留前 `num_siftings` 个 IMFs
        for i in range(min(num_siftings, imfs.shape[0])):
            E_IMFs[r, :, i] = imfs[i]
    
    # 所有实验的 IMFs 平均值
    mean_IMFs = np.mean(E_IMFs, axis=0)
    
    return mean_IMFs

# 假设您有一个名为 'data1' 的 DataFrame其中包含一个 'Power' 列
data_power = data1['Power'].values

# 定义分解的数据窗口大小
window_size = 104256

# 遍历以 'window_size' 为单位的数据块
for i in range(0, len(data_power), window_size):
    # 提取当前数据块
    current_data = data_power[i:i+window_size]
    
    # 对当前数据块应用 ICEEMDAN 分解
    IMFs = ICEEMDAN(current_data)
    
    # 创建一个新的 DataFrame 来保存 ICEEMDAN 分解结果
    data_ICEEMDAN = pd.DataFrame(IMFs, columns=[f'IMF{i}' for i in range(IMFs.shape[1])])
    
    # 计算 IMFs 的总和
    IMFs_sum = data_ICEEMDAN[[f'IMF{i}' for i in range(IMFs.shape[1])]].sum(axis=1)
    
    # 计算 IMFs 总和与原始信号之间的差值
    residue = current_data - IMFs_sum
    
    # 将残差添加到 DataFrame
    data_ICEEMDAN['Residue'] = residue
    
    # 打印当前数据块的分解结果
    print(f"数据块 {i+1}-{i+len(current_data)} 的分解结果:")
    print(data_ICEEMDAN)
In [ ]:
# 将分解后的 IMFs 与残差相加以恢复原始数据
reconstructed_signal = IMFs_sum + residue

# 绘制重构的数据与原始数据进行比较
plt.figure(figsize=(30, 18))
plt.plot(current_data[0:2900], label='Original Signal', color='blue')
plt.plot(reconstructed_signal[0:2900], label='Reconstructed Signal', color='red')
plt.xlabel('Time')
plt.ylabel('Amplitude')
plt.title('Comparison between Original and Reconstructed Signal')
plt.legend()
plt.grid(True)
plt.show()
In [ ]:
import matplotlib.pyplot as plt

# 设置全局字体大小
plt.rcParams.update({'font.size': 60})  # 设置字体大小为 16

# 在这里放置您的绘图代码
num_imfs = IMFs.shape[1]

plt.figure(figsize=(64,128))

# 绘制每个 IMF
for i in range(num_imfs):
    if i <= 19:  # 只绘制前 14 个 IMF
        plt.subplot(num_imfs, 1, i + 1)
        plt.plot(data_ICEEMDAN[f'IMF{i}'], label=f'IMF {i}')
        plt.legend()
plt.legend()

# 绘制残差
plt.subplot(num_imfs + 1, 1, num_imfs + 1)
plt.plot(data_ICEEMDAN[f'IMF{17}'], label='Residue', color='red')
plt.legend()

plt.tight_layout()
plt.show()
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import welch

def plot_frequency_spectrum(signal, sampling_rate, title):
    """
    绘制信号的频谱图。
    
    参数:
    - signal: 输入信号
    - sampling_rate: 信号的采样率
    - title: 图表标题
    """
    f, Pxx = welch(signal, fs=sampling_rate, nperseg=len(signal))
    plt.figure(figsize=(10, 5))
    plt.semilogy(f, Pxx)
    plt.title(title)
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Power spectral density')
    plt.grid(True)
    plt.show()

def compute_zero_crossings(signal):
    """
    计算信号的过零率。
    """
    zero_crossings = np.where(np.diff(np.sign(signal)))[0]
    zero_crossing_rate = len(zero_crossings) / len(signal)
    return zero_crossing_rate

def classify_frequency_component(imfs, threshold):
    """
    将每个 IMF 分为高频和低频成分。
    """
    high_frequency_imfs = []
    low_frequency_imfs = []
    for i in range(imfs.shape[1]):
        imf = imfs[:, i]
        zero_crossing_rate = compute_zero_crossings(imf)
        if zero_crossing_rate > threshold:
            high_frequency_imfs.append(imf)
        else:
            low_frequency_imfs.append(imf)
    return high_frequency_imfs, low_frequency_imfs

# 定义过零率的阈值
threshold = 0.2  # 可根据具体情况调整阈值

# 根据过零率判断高频和低频成分
high_freq_imfs, low_freq_imfs = classify_frequency_component(IMFs, threshold)
sampling_rate = 1000 
# 可选:绘制高频和低频成分的频谱图
for i, imf in enumerate(high_freq_imfs):
 plot_frequency_spectrum(imf, sampling_rate, f'High Frequency IMF {i+1}')

for i, imf in enumerate(low_freq_imfs):
 plot_frequency_spectrum(imf, sampling_rate, f'Low Frequency IMF {i+1}')
In [ ]:
# 打印高频和低频成分的 IMF 列表
print("High Frequency IMFs:")
for i, imf in enumerate(high_freq_imfs):
    print(f"IMF {i+1}: {imf}")

print("\nLow Frequency IMFs:")
for i, imf in enumerate(low_freq_imfs):
    print(f"IMF {i+1}: {imf}")
In [ ]:
import pandas as pd

# 将高频和低频信号相加
high_freq_sum = np.sum(high_freq_imfs, axis=0)
low_freq_sum = np.sum(low_freq_imfs, axis=0)
In [ ]:
high_freq_sum
In [ ]:
low_freq_sum
In [ ]:
residue
In [ ]:
re_low=residue+low_freq_sum
In [ ]:
re_high=residue+high_freq_sum
re_high
In [ ]:
# 指定文件路径和文件名保存DataFrame到CSV文件中
df_low = pd.DataFrame(low_freq_sum, columns=['column_name'])
df_low.to_csv('iceemdan_reconstructed_data_low.csv', index=False)
In [ ]:
# 指定文件路径和文件名保存DataFrame到CSV文件中
df_high = pd.DataFrame(high_freq_sum, columns=['column_name'])
df_high.to_csv('iceemdan_reconstructed_data_high.csv', index=False)
In [ ]:
# 指定文件路径和文件名保存DataFrame到CSV文件中
df_high = pd.DataFrame(residue, columns=['column_name'])
df_high.to_csv('iceemdan_reconstructed_data_residue.csv', index=False)
In [ ]:
# 指定文件路径和文件名保存DataFrame到CSV文件中
df_re_low = pd.DataFrame(re_low, columns=['column_name'])
df_re_low.to_csv('iceemdan_reconstructed_data_re_low.csv', index=False)
In [ ]:
# 指定文件路径和文件名保存DataFrame到CSV文件中
df_re_high = pd.DataFrame(re_high, columns=['column_name'])
df_re_high.to_csv('iceemdan_reconstructed_data_re_high.csv', index=False)
In [ ]:
IMFs_sum
In [ ]:
# 指定文件路径和文件名保存DataFrame到CSV文件中
df_high = pd.DataFrame(IMFs_sum, columns=['column_name'])
df_high.to_csv('iceemdan_reconstructed_data_IMFs_sum.csv', index=False)
In [ ]: