改进算法求1D numpy数组的局部极大值

时间:2018-02-05 20:41:37

标签: python arrays algorithm numpy

我正在尝试找到函数f(x) = (sin(x)/x)^2的局部最大值。 对于近似解,我初始化了两个变量xy,并首先绘制了一个图形以具有可视化表示。

x = np.linspace(-20.0, 20.0, num=int((20+20)/0.01)) 
y = np.power(np.sin(x)/x, 2)
plt.plot(x, y, 'r.', markersize= 1)
plt.show()  

这显示graph

然后我尝试创建一个算法来查找Maxima:

def returnMaxima(num, x, y):
    """
    number, np.array, np.array -> list
    num: number of maxima needed | x: x 1D array | y: y 1D array
    returns [[x1,y1], [x2,y2]...] in descending order of y
    """
    allMaximaPoints = [] # stores all Maxima points
    reqMaximaPoints = [] # stores num Maxima points
    for i in range(y.size): 
        # for first y value
        if i == 0: 
            if y[i] > y[i+1]:
                allMaximaPoints += [[x[i], y[i]], ]
        # for last y value
        elif i == y.size - 1:
            if y[i] > y[i-1]:
                allMaximaPoints += [[x[i], y[i]], ]
        # for rest y values
        else: 
            if y[i] > y[i-1] and y[i] > y[i+1]:
                allMaximaPoints += [[x[i], y[i]], ]
    # extract largest maximas from allMaximaPoints
    while num > 0: 
        reqMaximaPoints += [max(allMaximaPoints, key=lambda item:item[1]),]
        del allMaximaPoints[allMaximaPoints.index(max(allMaximaPoints, key=lambda item:item[1]))]
        num -= 1
    return reqMaximaPoints

当我尝试returnMaxima(2, x, y)时,我得到[[-4.4961240310077528, 0.04719010162459622], [4.4961240310077528, 0.04719010162459622]]

这是错误的,因为它跳过x = 0处的局部最大值。我怀疑是因为y[i-1] y[i+1]y[i]附近的x=0y[i]值大约等于导致代码的else: if y[i] > y[i-1] and y[i] > y[i+1]: allMaximaPoints += [[x[i], y[i]], ]

x = np.linspace(-20.0, 20.0, num=int((20+20)/0.01))

不考虑那一点。这是因为当我将x = np.linspace(-20.0, 20.0, num=int((20+20)/0.1))更改为x=0,即x中的较大步数时,才能正确找到>处的局部最大值。但是,即使我将上述代码中的>=符号更改为x=0,{{1}}处的最大值仍未计算在内。

为什么会这样?我应该如何改进我的代码以获得正确的结果? 谢谢!

2 个答案:

答案 0 :(得分:1)

使用scipy.signal.find_peaks_cwt之类的东西可能会更好。类似的东西:

indices = scipy.signal.find_peaks_cwt(y, [1, 2, 3, 4], noise_perc=50)
plt.plot(x, y)
plt.plot(x[indices], y[indices], 'r.')
plt.show()

结果:

Peaks

答案 1 :(得分:0)

简短回答:x永远不会为0(你可能也不希望它是。)

我们可以通过运行

进行测试
public class AllLoxMap extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    LocationManager lm;
    LocationListener ll;

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (ContextCompat.checkSelfPermission(this, Manifest.permission
                        .ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);

                    Location lastKnownLocation = lm.getLastKnownLocation(LocationManager
                            .GPS_PROVIDER);

                    if (lastKnownLocation != null) {
                        updateMap(lastKnownLocation);
                    }
                }
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_all_lox_map);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        ll = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {

                updateMap(location);
            }

            @Override
            public void onStatusChanged(String s, int i, Bundle bundle) {

            }

            @Override
            public void onProviderEnabled(String s) {

            }

            @Override
            public void onProviderDisabled(String s) {

            }
        };

        if (ContextCompat.checkSelfPermission(this, Manifest.permission
                .ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission
                    .ACCESS_FINE_LOCATION}, 1);
        } else {
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);

            Location lastKnownLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

            if (lastKnownLocation != null) {
                updateMap(lastKnownLocation);
            }
        }
    }

    public void updateMap(Location location) {

        LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());

        mMap.clear();
        mMap.addMarker(new MarkerOptions().position(userLocation).title("Marker"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
    }
}

这实际上是幸运的,因为x = 0会导致运行时警告,并且由于除以0而产生“nan”(非数字)值。问题是函数未定义为0。

否则,您基本上是正确的,为什么它不起作用。如果您将In [53]: 0 in x Out[53]: False 替换为>,您会看到输出不同:

>=

这实际上是“正确的”输出,因为它们是最大的值,并且是x最接近0的值。