There was a missing ( in front of your last Get-VMHost. You also just want the attribute NumCPU, not an object containing one attribute NumCPU so I've changed line 3 a little
Get-VM | Select Name, @{N="Cluster";E={Get-Cluster -VM $_}},
@{N= "ESX Host";E={Get-VMHost -VM $_}},
@{N= "NumCPU";E={(Get-VMHost -VM $_).NumCPU}},
@{N= "Cores";E={(Get-VMHost -VM $_ | Get-View).Hardware.CpuInfo.NumCpuCores}}
If you're running this for a large # of VMs you may want to look at optimizing it a bit. Rather than calling "Get-VMHost" multiple times you can restructure a bit so its only called once
Get-VM | Select Name, @{N="Cluster";E={Get-Cluster -VM $_}},
@{N= "ESX Host";E={ $Script:VMH = (Get-VMHost -VM $_ ); $Script:VMH.Name }},
@{N= "NumCPU";E={$Script:VMH.NumCPU}},
@{N= "Cores";E={$Script:VMH.ExtensionData.Hardware.CpuInfo.NumCpuCores}}
The 2nd piece of code is a little over 2x faster than the first since Get-VMHost isn't being called multiple times
One other quick thing, if you're looking for the number of CPUs (i.e. how many sockets) then replace $Script:VMH.NumCPU with $Script:VMH.ExtensionData.Hardware.CpuInfo.NumCpuPackages; the NumCPU attribute of the host object is actually the number of cores so that can be a bit misleading