梯度下降算法结果图错误

梯度下降算法出的结果不对
RunModel.py

import numpy as np
from SystemModel import System_Model
from Environment import NumberOfUAVs,NumberOfUsers,F_c,learning_rate,num_iterations

def main():
    env = System_Model()

    Distance_U2K = env.Get_Distance_U2K(env.PositionOfUAVs, env.PositionOfUsers, NumberOfUAVs, NumberOfUsers)
    print("-------UAV和User的距离--------")
    print(Distance_U2K)

    service_quality = env.evaluate_service_quality(Distance_U2K)
    print("服务质量:", service_quality)

    find_optimal_uav = env.find_optimal_uav()
    print("无人机:", find_optimal_uav)

    uav_mapping = {"U0": 0, "U1": 1, "U2": 2}  # 根据你的实际情况进行修改
    n = min(len(service_quality), len(find_optimal_uav))
    features = []
    for i in range(n):
        if service_quality[i] == "优秀":
            quality = 2
        elif service_quality[i] == "良好":
            quality = 1
        elif service_quality[i] == "一般":
            quality = 0
        else:
            quality = -1
        uav_index = uav_mapping.get(find_optimal_uav[i], -1)  # 查找无人机对应的索引,找不到则设为-1
        if uav_index != -1:
            features.append([1, quality, uav_index])
    features = np.array(features, dtype=float)
    print(features)
    labels = np.array([20, 30, 40])  # khz 带宽(切片修改为与 features 长度匹配)
    # 执行梯度下降算法
    env.gradient_descent(features, labels)

    # 可视化结果
    env.plot_results(features, labels)

if __name__ == '__main__':
    main()

SystemModel.py

import numpy as np
import matplotlib.pyplot as plt
import math
import pandas as pd
import copy

from Environment import MAXUserspeed,UAV_Speed,UserNumberPerCell,NumberOfUAVs,NumberOfCells,NumberOfUsers,learning_rate,num_iterations


class System_Model:
    def __init__(
            self,
    ):
        self.learning_rate = learning_rate
        self.num_iterations = num_iterations
        self.theta = None
        # 初始化无人机及位置
        self.UAVspeed = UAV_Speed
        self.UAV_number = NumberOfUAVs
        self.UserperCell = UserNumberPerCell
        self.U_idx = np.arange(NumberOfUAVs)  # set up serial number for UAVs 为无人机设置序列号
        self.PositionOfUAVs = pd.DataFrame(
            np.zeros((3, NumberOfUAVs)),
            columns=self.U_idx.tolist(),  # Data frame for saving UAVs' position  将Dataframe格式的数据转成List数据类型
        )
        self.PositionOfUAVs.iloc[0, :] = [100, 200, 400]  # UAVs' initial x
        self.PositionOfUAVs.iloc[1, :] = [100, 400, 200]  # UAVs' initial y
        self.PositionOfUAVs.iloc[2, :] = [100, 100, 100]  # UAVs' initial z

        # 初始化用户和位置
        self.User_number = NumberOfUsers
        self.K_idx = np.arange(NumberOfUsers)  # set up serial number for users
        self.PositionOfUsers = pd.DataFrame(
            np.random.random((3, NumberOfUsers)),
            columns=self.K_idx.tolist(),  # Data frame for saving users' position
        )
        self.PositionOfUsers.iloc[0, :] = [204.91, 493.51, 379.41, 493.46, 258.97, 53.33]  # users' initial x
        self.PositionOfUsers.iloc[1, :] = [219.75, 220.10, 49.81, 118.10, 332.59, 183.11]  # users' initial y
        self.PositionOfUsers.iloc[2, :] = 0  # users' hight is assumed to be 0

        # 记录最开始的位置
        self.Init_PositionOfUsers = copy.deepcopy(self.PositionOfUsers)
        # copy.deepcopy()函数是一个深复制函数。所谓深复制,就是从输入变量完全复刻一个相同的变量,无论怎么改变新变量,原有变量的值都不会受到影响。
        self.Init_PositionOfUAVs = copy.deepcopy(self.PositionOfUAVs)

        # initialize a array to store state 初始化一个数组来存储状态
        self.State = np.zeros([1, NumberOfUAVs * 3 + NumberOfUsers], dtype=float)

        # data frame to save distance
        self.Distence = pd.DataFrame(
            np.zeros((self.UAV_number, self.User_number)),
            columns=np.arange(self.User_number).tolist(), )
        # pd.DataFrame创建了一个二维表,np.zeros((self.UAV_number, self.User_number))多维数组,columns的值相当于列索引

        # data frame to save pathloss路径损耗
        self.Propergation_Loss = pd.DataFrame(
            np.zeros((self.UAV_number, self.User_number)),
            columns=np.arange(self.User_number).tolist(), )


    # 用户随机移动
    def User_randomMove(self, MAXspeed, NumberofUsers):
            self.PositionOfUsers.iloc[[0, 1], :] += np.random.randn(2, NumberofUsers) * MAXspeed  # users random move
            return

    # this function is for calculating the distance between users and UAVs
    def Get_Distance_U2K(self, UAV_Position, User_Position, UAVsnumber,
                             Usersnumber):

            for i in range(UAVsnumber):
                for j in range(Usersnumber):
                    self.Distence.iloc[i, j] = np.linalg.norm(
                        UAV_Position.iloc[:, i] - User_Position.iloc[:,
                                                  j])  # calculate Distence betwen UAV i and User j
                    # x_norm = np.linalg.norm(x, ord=None, axis=None, keepdims=False)
                    # 默认参数ord = None,axis = None,keepdims = False x: 表示矩阵

            return self.Distence

    def evaluate_service_quality(self, distance_U2K):
        service_quality = []
        for i in range(distance_U2K.shape[0]):
            for j in range(distance_U2K.shape[1]):
                distance = distance_U2K.iloc[i, j]
                if distance < 150:
                    result = "优秀"
                elif distance < 250:
                    result = "良好"
                elif distance < 350:
                    result = "一般"
                else:
                    result = "差"
                # service_quality.append((distance, result))这个是包含距离值和评价结果
                service_quality.append((result))
        return service_quality

    def Get_Propergation_Loss(self, distence_U2K, UAV_Position, UAVsnumber, Usersnumber,
                              f_c):

        for i in range(
                UAVsnumber):  # Calculate average loss for each user,  this pathloss model is for 22.5m<h<300m d(2d)<4km
            for j in range(Usersnumber):
                UAV_Hight = UAV_Position.iloc[2, i]
                D_H = np.sqrt(np.square(distence_U2K.iloc[i, j]) - np.square(UAV_Hight))  # calculate distance
                # calculate the possibility of LOS/NLOS
                d_0 = np.max([(294.05 * math.log(UAV_Hight, 10) - 432.94), 18])
                p_1 = 233.98 * math.log(UAV_Hight, 10) - 0.95
                if D_H <= d_0:
                    P_Los = 1.0
                else:
                    P_Los = d_0 / D_H + math.exp(-(D_H / p_1) * (1 - (d_0 / D_H)))

                if P_Los > 1:
                    P_Los = 1

                P_NLos = 1 - P_Los

                # calculate the passlos for LOS/NOLS
                L_Los = 30.9 + (22.25 - 0.5 * math.log(UAV_Hight, 10)) * math.log(distence_U2K.iloc[i, j],
                                                                                  10) + 20 * math.log(f_c, 10)

                L_NLos = np.max([L_Los,
                                 32.4 + (43.2 - 7.6 * math.log(UAV_Hight, 10)) * math.log(distence_U2K.iloc[i, j],
                                                                                          10) + 20 * math.log(f_c, 10)])

                Avg_Los = P_Los * L_Los + P_NLos * L_NLos  # average pathloss
                gain = np.random.rayleigh(scale=1, size=None) * pow(10, (-Avg_Los / 10))  # random fading
                self.Propergation_Loss.iloc[i, j] = gain  # save pathloss

        return self.Propergation_Loss

    def find_optimal_uav(self):
        min_loss = np.inf
        optimal_uav = []

        for i in range(NumberOfUAVs):  # Assuming UAVsnumber is defined
            total_loss = np.sum(self.Propergation_Loss.iloc[i, :])  # Calculate total loss for the current UAV

            if total_loss < min_loss:
                min_loss = total_loss
                optimal_uav = [i]
            elif total_loss == min_loss:
                optimal_uav.append(i)

        return ["U{}".format(uav_index) for uav_index in optimal_uav]

    #计算S2A梯度下降算法
    def gradient_descent(self, features, labels):
        num_samples, num_features = features.shape
        self.coefficients = np.zeros(num_features)

        for _ in range(self.num_iterations):
            predictions = self.predict(features)
            errors = predictions - labels
            gradient = np.dot(features.T, errors) / num_samples
            self.coefficients -= self.learning_rate * gradient

    def predict(self, features):
        return np.dot(features, self.coefficients)

    def plot_results(self, features, labels):
        plt.scatter(features[:, 1], labels, color='b', label='Actual')
        plt.plot(features[:, 1], self.predict(features), color='r', label='Predicted')
        plt.xlabel('features')
        plt.ylabel('labels')
        plt.legend()
        plt.savefig("E:\paper\TYUTpaper\img/costs_plot.png")
        plt.show()


Environment

#迭代更新参数的次数
learning_rate = 0.1
num_iterations = 1000

F_c = 2  # carrier frequency/GHz 载频/GHz

# set up users' speed设置用户速度
MAXUserspeed = 0.5  # m/s
UAV_Speed = 5  # m/s
UserNumberPerCell = 2  # user number per UAV每架无人机服务两个用户
NumberOfUAVs = 3  # number of UAVs无人机的数量
NumberOfCells = NumberOfUAVs  # Each UAV is responsible for one cell每架无人机负责一个小区(小区数量等于无人机数量)
NumberOfUsers = NumberOfUAVs * UserNumberPerCell  # 用户数量等于无人机数*每架无人机服务的用户数

结果图为

img

目的是求得卫星的最佳 S2A 单播带宽价格,应该如何修改呢